ROW_NUMBER () 与 PARTITION 组合妙用

简介:

前几天在一个群里面,有位网友问:在一个Book表里面里有字段AuthorID与Author表关联,现在要求按PublishDate字段倒序 排列,列出每个作者的前五本书。要求有没有一条语句搞定的. 当时有个网友说不能一条语句解决问题,说只能用游标或临时表来解决。恰好我前阵子在整报表时遇到过类似的问题,当时解决过这个问题。当时我就告诉他用 ROW_NUMBER与PARTITION来解决(前提是SQL SERVER 05或以上版本)。恰好现在有时间。正好把这个整理一下,即是对知识的梳理、巩固、总结,也希望能给其他人一些帮助

 

建表脚本

代码

IF OBJECT_ID(N'Author') IS NOT NULL
BEGIN    
    DROP TABLE dbo.Author;
END
ELSE
    BEGIN
        CREATE TABLE dbo.Author
        (
            AuthorID      INT IDENTITY(1,1) PRIMARY KEY,
            AuthorName    NVARCHAR(50),
            NickName      NVARCHAR(50),
            Place         NVARCHAR(120),
            BirthDay      SMALLDATETIME
        )
    END
GO

IF OBJECT_ID(N'Book') IS NOT NULL 
    BEGIN
        DROP TABLE dbo.Book ;
    END
ELSE 
    BEGIN
    
        CREATE TABLE dbo.Book
        (
            ID                    INT IDENTITY(1, 1) ,
            BookName              NVARCHAR(35) ,            --书名
            PublishDate           DATETIME ,                --出版时间
            Publisher             NVARCHAR(50) ,            --出版商
            BookType              INT ,                     --书籍类型
            AuthorID              INT FOREIGN KEY REFERENCES dbo.Author(AuthorID)
        )
    END
GO


代码

--生成实验数据
INSERT INTO dbo.Author
VALUES('张三', '三峰', '北京', '1973-12-28')

INSERT INTO dbo.Author
VALUES ('王五', '绝望的中春天', '湖南', '1978-5-23' )

INSERT INTO dbo.Author
VALUES ('赵四', '赵四', '上海', '1978-5-23' )


INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '张三书1' , 
          '1988-12-24' ,
          '北京图书出版社' , 
, 

        )
        
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '张三书2' , 
          '1983-12-04' ,
          '长城图书出版社' , 
, 

        )
       
       
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '张三书3' , 
          '1995-12-19' ,
          '教育图书出版社' , 
, 

        )
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '张三书4' , 
          '1996-12-04' ,
          '教育图书出版社' , 
, 

        )
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '张三书5' , 
          '2004-04-26' ,
          '教育图书出版社' , 
, 

        )
        
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '张三书6' , 
          '2009-12-15' ,
          '教育图书出版社' , 
, 

        )
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '王五1' , 
          '2003-06-15' ,
          '教育图书出版社' , 
, 

        )
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '王五2' , 
          '2007-09-25' ,
          '上海图书出版社' , 
, 

        )
        
        
INSERT INTO dbo.Book
        ( BookName ,
          PublishDate ,
          Publisher ,
          BookType ,
          AuthorID
        )
VALUES  ( '赵四1' , 
          '2010-09-25' ,
          '上海图书出版社' , 
, 

        )




下面就是解决问题的脚本

代码

SELECT * FROM
     (
         SELECT  ROW_NUMBER() OVER (PARTITION  BY A.AuthorID ORDER BY  B.PublishDate DESC) AS RowNum,
                 A.AuthorName, B.BookName, B.PublishDate
         FROM 
         dbo.Book B
         INNER JOIN dbo.Author A ON A.AuthorID = B.AuthorID
     ) T
     WHERE T.RowNum <= 5

相关文章
|
SQL Go
【SQL】ROW_NUMBER() OVER(partition by 分组列 order by 排序列)用法详解+经典实例
【SQL】ROW_NUMBER() OVER(partition by 分组列 order by 排序列)用法详解+经典实例目录 0、填充数据1、使用row_number()函数对订单进行编号,按照订单时间倒序。
13043 0
COUNT DISTINCT ROW_NUMBER DENSE_RANK 以及对COUNT去重(非PARTITION)
1:COUNT DISTINCT         SELECT          COUNT(DISTINCT [QS_QuestionStem].Id)  AS ReqCount1,         [QS_QuestionStem].
768 0
|
11月前
|
算法
Leetcode 313. Super Ugly Number
题目翻译成中文是『超级丑数』,啥叫丑数?丑数就是素因子只有2,3,5的数,7 14 21不是丑数,因为他们都有7这个素数。 这里的超级丑数只是对丑数的一个扩展,超级丑数的素因子不再仅限于2 3 5,而是由题目给定一个素数数组。与朴素丑数算法相比,只是将素因子变了而已,解法还是和朴素丑数一致的。
95 1
|
4月前
|
存储 SQL 算法
LeetCode 题目 65:有效数字(Valid Number)【python】
LeetCode 题目 65:有效数字(Valid Number)【python】
|
5月前
|
存储 算法
【LeetCode力扣】单调栈解决Next Greater Number(下一个更大值)问题
【LeetCode力扣】单调栈解决Next Greater Number(下一个更大值)问题
41 0
|
11月前
|
存储
Leetcode Single Number II (面试题推荐)
给你一个整数数组,每个元素出现了三次,但只有一个元素出现了一次,让你找出这个数,要求线性的时间复杂度,不使用额外空间。
38 0
|
算法
LeetCode 414. Third Maximum Number
给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。
91 0
LeetCode 414. Third Maximum Number
|
存储
LeetCode 313. Super Ugly Number
编写一段程序来查找第 n 个超级丑数。 超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数。
92 0
LeetCode 313. Super Ugly Number
|
算法
LeetCode 306. Additive Number
累加数是一个字符串,组成它的数字可以形成累加序列。 一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。 给定一个只包含数字 '0'-'9' 的字符串,编写一个算法来判断给定输入是否是累加数。 说明: 累加序列里的数不会以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。
120 0
LeetCode 306. Additive Number
|
算法
LeetCode 268. Missing Number
给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。
86 0
LeetCode 268. Missing Number