row_number() over (partition by....order by...)用法

表结构:表A:名称,创建人

    表B:表Aid,接收人

    表C:表Aid,内容,发送人,接收人,状态

需求分析:创建人发送内容给接收人消息,接收人回复。创建人,接收人登陆入消息页面,需看到了解到属于自己的消息以及自己创建的消息是否有回复。

解析:当admin创建了一条消息给longer,会往A,B,C中插入数据,表C的状态为1为已读。admin登陆页面显示为:名称,发起人为admin,状态为已读

   当longer登陆时页面显示为:名称,发起人admin,状态为未读。

     若longer查看消息并回复一条消息时。 longer回到页面,则显示为已读,即使在上一步,不回复,查看了也是显示为已读状态。

    当admin登陆到消息页面时,该信息状态显示为未读,若longer没有回复消息,那么显示的就是已读。

根据表结构以及需求,剖析出来就是要分解为两个查询语句,可能会更好入手解决,面对可以解析为两手着手的问题,一般就会习惯于分成两步考虑。

首先考虑先解决创建人创建消息的查询,这里要解决的问题就是,我是创建人,发送到的longer消息被读取回复的情况。也就是通过表A查询出本次登陆用户创建的消息以及对应到表C里是否有人回复并未读取的状况。那问题就来了,若我这条消息同时发送给了三个人,九点的时候有人回复了,我登陆并查看后,十点另一个人回复了,然后再通过普通的级联查询已经不能满足,也就是说此时查询会查询出两条数据状态分别为1和2,已读和未读。那此时要求的就是当有2时候要显示未读,去除1的数据。自然就会想到排序分组,排序后给其分状态位标识。这么说可能比较难理解。直接来看句子:

  

SELECT * FROM (
select ROW_NUMBER() OVER(PARTITION BY m.id ORDER BY c.content_status desc)RN,
        m.id,m.title,m.establish_human humanid, decode(m.delflag,'0','0') status, nvl(c.content_status,'1') type
 from ns_message m left join ns_message_content c on m.establish_human=c.receive_human
       and m.id=c.messageid
       where m.delflag=0 and m.establish_human='adminID'
  )where rn=1

  注意:ROW_NUMBER函数是先排序后再计算行号码的。翻译到我们日常理解就是有你,你则是1他是2,没有你他进阶为1.

同理推断出,admin是接收者的消息(这里直接贴句子):

select rn, id, title, humanid, status, type
          from (select ROW_NUMBER() OVER(PARTITION BY m.id, m.title order by c.content_status) RN,
                       m.id,
                       m.title,
                       m.establish_human humanid,
                       decode(m.delflag, '0', '1') status,
                       c.content_status type
                  from ns_message_human h
                  left join ns_message m on h.messageid = m.id
                  left join ns_message_content c on m.id = c.messageid
                 where m.delflag = 0
                   and h.receivehumanid = 'adminID'
                   and c.receive_human = 'adminID')

  最后就是利用union进行整合,最终sql语句就是:

  select * from 
( SELECT * FROM (
select ROW_NUMBER() OVER(PARTITION BY m.id ORDER BY c.content_status desc)RN,
        m.id,m.title,m.establish_human humanid, decode(m.delflag,'0','0') status, nvl(c.content_status,'1') type
 from ns_message m left join ns_message_content c on m.establish_human=c.receive_human
       and m.id=c.messageid
       where m.delflag=0 and m.establish_human='402884124a3c15e9014a3c1aa0670001'
  )where rn=1 
  union
        select rn, id, title, humanid, status, type
          from (select ROW_NUMBER() OVER(PARTITION BY m.id, m.title order by c.content_status) RN,
                       m.id,
                       m.title,
                       m.establish_human humanid,
                       decode(m.delflag, '0', '1') status,
                       c.content_status type
                  from ns_message_human h
                  left join ns_message m on h.messageid = m.id
                  left join ns_message_content c on m.id = c.messageid
                 where m.delflag = 0
                   and h.receivehumanid = '40288567400553f501400554c7b00044'
                   and c.receive_human = '40288567400553f501400554c7b00044')
         where rn = 1)

  这里只是大概对于ROW_NUMBER的使用进行了举例子,具体的含义概念,谷歌一番,可能效果会更好点。我们代码世界的理解方式:看+敲=理解

posted @ 2017-03-20 16:09  理解龙儿  阅读(1082)  评论(0编辑  收藏  举报