SQL Server 分组取 Top 笔记(row_number + over 实现)

 

先看SQL语句(注意:这是在SQL Server 2005+ [包括2005] 的版本才支持的哦,o(∩_∩)o 哈哈~)

SELECT

  col1,col2,col3

FROM table1 AS a WITH(NOLOCK) INNER JOIN(

  // 第一部分代码

  SELECT

    b1.col1,b1.col2,b1.col3,

    ROW_NUMBER() OVER ( PARTITION BY b1.分组列名 ORDER BY b1.排序列 DESC/ASC ) AS sortedId

  FROM table1 AS b1 WITH(NOLOCK)

) AS b  WITH(NOLOCK) ON a.id=b.id

WHERE b.sortedId>= 需要 获取的 top 值

----------------------------------------------------------------------------------------------------------------------------------

// 第一部分代码(为什么这样写?)

重点是记录一下自己对 ROW_NUMBER() OVER ( ...... ) 组合的理解。

记得有一次面试,遇到这样一个问题( 怎么获取一张表 第30-40的数据记录,注意:表的主键id,可能不连续)。

大牛看到后,肯定会喷我的,那么简单,你说个毛啊。

是的,您喷得对,确实很很简单嘛。

SELECT

  id,col1,col2

FROM table1 a INNER JOIN  (

  SELECT 

    id,

    ROW_NUMBER() OVER ( ORDER BY ID ASC ) as rowId

  FROM table1 b1

) AS b ON a.id = b.id 

WHERE b.rowId BETWEEN $strartId AND $endId

 

------------------------------------------------------------------------------------------------------------------------

好吧,言归正传

ROW_NUMBER() OVER ( [ PARTITION BY 分组列名 ] ORDER BY 排序列 DESC/ASC ) AS sortedId 

ROW_NUMBER() 为每一行数据分配一个连续的编号,这个编号可以一样的哦,它取决于后面的 OVER( [表达式] ORDER BY xxx DESC/ASC ) 

PARTITION BY col1 :通过 OVER 告诉 ROW_NUMBER() ,如果 2行(或者更多行) col1值是一样的,你就给我一样的编号,不要分配新的编号给我,谢谢~~ o(∩_∩)o 

也就是说 用 【 ROW_NUMBER() OVER ( [ PARTITION BY col1] ORDER BY 排序列 DESC/ASC ) AS sortedId】生成的sortedId 实际上是按照 col1 分组了的

 

好嘛,扯完了,举个栗子呗。加深自己的印象。

有一张学生考试成绩表 stuSorceInfo(统计每一科成绩的第一名 [ 前三名,前N ])

 

主键ID    学生ID      科目ID      分数

id      studentId    subjectId    score

 1                 1         1          81

-------------------------------------------------------------

 2                 1         2         88

-------------------------------------------------------------

 3                2         1          80

-------------------------------------------------------------

 4                2         2          98

-------------------------------------------------------------

获取 每一科成绩的第一名 

SELECT a.* FROM stuSorceInfo a WHERE INNER JOIN  (

  SELECT

    b1.studentId,

    ROW_NUMBER( PARTTION BY subjectId ORDER BY b1.socre DESC ) sortedId

  FROM stuSorceInfo b1

) AS b ON a.id=b.id WHERE b.sortedId=1 (第一名:=1,前三名:<=3 ,前N名:<=N)

 

参考资料:

http://blog.csdn.net/wuzhengqing1/article/details/8024634

http://www.cnblogs.com/gy51Testing/archive/2012/07/26/2609832.html

感谢每一位blog朋友的分享,谢谢!o(∩_∩)o 哈

 

posted on 2015-07-06 10:56  oceanho  阅读(481)  评论(0编辑  收藏  举报

导航