`

row_number()over函数的使用(转)

阅读更多

row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的).

  与rownum的区别在于:使用rownum进行排序的时候是先对结果集加入伪列rownum然后再进行排序,而此函数在包含排序从句后是先排序再计算行号码.

  row_number()和rownum差不多,功能更强一点(可以在各个分组内从1开时排序).

  rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内).

  dense_rank()l是连续排序,有两个第二名时仍然跟着第三名。相比之下row_number是没有重复值的 .

  lag(arg1,arg2,arg3):
arg1是从其他行返回的表达式
arg2是希望检索的当前行分区的偏移量。是一个正的偏移量,时一个往回检索以前的行的数目。
arg3是在arg2表示的数目超出了分组的范围时返回的值。

看几个SQL语句:

语句一:

select row_number() over(order by sale/cnt desc) as sort, sale/cnt
from (
select -60 as sale,3 as cnt from dual union
select 24 as sale,6 as cnt from dual union
select 50 as sale,5 as cnt from dual union
select -20 as sale,2 as cnt from dual union
select 40 as sale,8 as cnt from dual);

执行结果:

          SORT       SALE/CNT
---------- ----------
             1             10
             2              5
             3              4
             4            -10
             5            -20

 

语句二:查询员工的工资,按部门排序

select ename,sal,row_number() over (partition by deptno order by sal desc) as sal_order from scott.emp;

执行结果:

ENAME                           SAL      SAL_ORDER
-------------------- ---------- ----------
KING                           5000              1
CLARK                          2450              2
MILLER                         1300              3
SCOTT                          3000              1
FORD                           3000              2
JONES                          2975              3
ADAMS                          1100              4
SMITH                           800              5
BLAKE                          2850              1
ALLEN                          1600              2
TURNER                         1500              3
WARD                           1250              4
MARTIN                         1250              5
JAMES                           950              6

已选择14行。

语句三:查询每个部门的最高工资

select deptno,ename,sal from
     (select deptno,ename,sal,row_number() over (partition by deptno order by sal desc) as sal_order
         from scott.emp) where sal_order <2;

执行结果:

       DEPTNO ENAME                          SAL
---------- -------------------- ----------
           10 KING                          5000
           20 SCOTT                         3000
           30 BLAKE                         2850

已选择3行。

语句四:

select deptno,sal,rank() over (partition by deptno order by sal) as rank_order from scott.emp order by deptno;

执行结果:

     DEPTNO         SAL RANK_ORDER
---------- ---------- ----------
         10        1300           1
         10        2450           2
         10        5000           3
         20         800           1
         20        1100           2
         20        2975           3
         20        3000           4
         20        3000           4
         30         950           1
         30        1250           2
         30        1250           2
         30        1500           4
         30        1600           5
         30        2850           6

已选择14行。

语句五:

select deptno,sal,dense_rank() over(partition by deptno order by sal) as dense_rank_order from scott.emp order by deptn;

执行结果:

     DEPTNO         SAL DENSE_RANK_ORDER
---------- ---------- ----------------
         10        1300                 1
         10        2450                 2
         10        5000                 3
         20         800                 1
         20        1100                 2
         20        2975                 3
         20        3000                 4
         20        3000                 4
         30         950                 1
         30        1250                 2
         30        1250                 2
         30        1500                 3
         30        1600                 4
         30        2850                 5

已选择14行。

语句六:

select deptno,ename,sal,lag(ename,1,null) over(partition by deptno order by ename) as lag_ from scott.emp order by deptno;

执行结果:

 

 

     DEPTNO ENAME                        SAL LAG_
---------- -------------------- ---------- --------------------
         10 CLARK                       2450
         10 KING                        5000 CLARK
         10 MILLER                      1300 KING
         20 ADAMS                       1100
         20 FORD                        3000 ADAMS
         20 JONES                       2975 FORD
         20 SCOTT                       3000 JONES
         20 SMITH                        800 SCOTT
         30 ALLEN                       1600
         30 BLAKE                       2850 ALLEN
         30 JAMES                        950 BLAKE
         30 MARTIN                      1250 JAMES
         30 TURNER                      1500 MARTIN
         30 WARD                        1250 TURNER

已选择14行。

很多年以后,还有很多程序员不知道SQL Server2005有了更方便的分页方法,这就是ROW_NUMBER()函数。我们知道SQL2000时代的分页方式是TOP加NOT IN截取中间数据,效率也是很不错的,但这两种效率到底如何呢,我们这次以一万、十万和百万数据量的数据做演示,比较这两种分页方式的效率。另外为何使用 TOP+NOT IN来和ROW_NUMBER()比较,是因为和游标方式及ISNULL方式分页来说,TOP+NOT IN方式效率更高。前人已有证明,可参考这篇文章:http://www.cnblogs.com/morningwang/archive/2009/01/02/1367277.html ,或者自行搜索更权威文章。

准备工作

准备工具:电脑(当然了o(∩_∩)o )和程序员一名。

同一测试环境,电脑配置如下,数据如有不实,请找周鸿祎~

建立数据表,插入相应数据。表结构如下,Id为自增长主键:

插入100万条测试数据:

user table3
go
declare @index int
set @index=0
while @index<1000000
    begin
        insert into Users(Name) values('walkingp')
        set @index=@index+1
    end

接下来先扫盲一下ROW_NUMBER()函数。

ROW_NUMBER()函数

ROW_NUMBER()函数是根据参数传递过来的order by子句的值,返回一个不断递增的整数值,也就是它会从1一直不断自增1,直到条件不再满足。例如表Users(Id,Name),使用以下sql语句进行查询: 

select id,name,row_number() over(order by Id desc) as rowNum from users where id<10
select id,name,row_number() over(order by Id) as rowNum from users where id<10

两条语句order by排序相反,执行结果如下:

孰优孰劣

以下两种情况,同样取500000到500100中间的数据。

1、使用ROW_NUMBER()函数。

SQL语句如下:

declare @time datetime
declare @ms int
set @time= getdate()
select Id,Name from (select row_number() over(order by Id) as rowNum,* from users) as t where rowNum between 500000 and 500100
set @ms=datediff(ms,@time,getdate())
print @ms--毫秒数

测试了几次,平均在250毫秒:

2、使用TOP加NOT IN方法。

SQL语句如下:

select top 100 * from users where Id not in
    (select top 500000 id from users order by id)
    order by id

平均在236毫秒:

好吧,一起执行看看结果:

或者你认为SQL存在缓存的问题,把两部分顺序对掉一下:

以上是百万数据量的对比,再看看1万条数据下的对比:

结论

通过以上对比可以我们可以得到这样的结论:在小数据量下(一般应该认为是10万以下,TOP+NOT IN分页方式效率要比ROW_NUMBER()高;在大数据量下(百万级)ROW_NUMBER()分页方式效率要更高一些。

分享到:
评论

相关推荐

    Oracle row_number()over

    这个示例中,我们使用 row_number()over 函数来生成一个部门内的薪水累计列,并将其与部门总和和每个人的薪水占部门总额的比例进行比较。 3. 部门从大到小排列,部门里各员工的薪水从高到低排列: ``` select ...

    ROW_NUMBER() OVER函数的基本用法

    2. 自动添加字段编号:可以使用 ROW_NUMBER() OVER 函数来自动添加字段编号。 3. 数据分析:可以使用 ROW_NUMBER() OVER 函数来对数据进行分析和排名。 ROW_NUMBER() OVER 函数是一个非常有用的函数,可以帮助我们...

    ROW_NUMBER()函数

    在本文中,我们将详细介绍 ROW_NUMBER() 函数的使用方法和优点,以及如何使用它来实现高效的数据分页。 ROW_NUMBER() 函数的使用方法 --------------------------- ROW_NUMBER() 函数的基本语法是:`ROW_NUMBER() ...

    oracle分析函数row_number() over()使用

    Oracle的分析函数row_number() over()是数据库查询中一种强大的工具,它用于对数据集进行分组和排序,尤其在处理重复数据或者实现排名时非常有用。在Oracle SQL中,row_number()函数会为每一行生成一个唯一的数字,...

    row_number,根据多个字段过滤,partition by

    使用`ROW_NUMBER()`函数与`PARTITION BY`子句 为了实现上述需求,可以采用SQL中的`ROW_NUMBER()`窗口函数配合`PARTITION BY`子句来完成。下面详细介绍这一过程: #### 2.1 `ROW_NUMBER()`函数概述 `ROW_NUMBER()...

    oracle row_number用法

    除了以上基础用法外,`ROW_NUMBER()`还可以与其他窗口函数组合使用,实现更复杂的数据分析需求。例如,结合`LAG()`和`LEAD()`函数可以实现数据的前后对比;与`RANK()`和`DENSE_RANK()`结合则可以进一步细化排序逻辑...

    02.hive内置函数--窗口分析函数--row_number_over.mp4

    02.hive内置函数--窗口分析函数--row_number_over.mp4

    SQL ROW_NUMBER()分页比较

    在 SQL Server 2005 中,使用 ROW_NUMBER() 函数可以实现分页功能,这种方法相比于 SQL Server 2000 中的分页方式效率要高出很多。但是,很多人在使用 ROW_NUMBER() 函数时,使用的方法并不正确。 在本文中,我们将...

    row_number.rar_SQL中row_number用法_number

    在SQL语言中,`ROW_NUMBER()`函数是一种非常重要的窗口函数,用于为查询结果集中的每一行分配一个唯一的整数。这个数字通常按照行的出现顺序进行分配,但也可以根据特定的排序条件进行调整。`ROW_NUMBER()`在数据...

    SQLServer中Partition By及row_number 函数使用详解

    `ROW_NUMBER()` 函数则是为每个分区分配一个唯一的行号,通常与 `OVER()` 子句一起使用。在 `OVER(PARTITION BY ... ORDER BY ...)` 中,`PARTITION BY` 定义了分区的依据,而 `ORDER BY` 规定了行号的排序规则。...

    SQL Server中row_number函数的常见用法示例详解

    select *,row_number() over(partition by column1 order by column2) as n from tablename 在上面语法中: PARTITION BY子句将结果集划分为分区。 ROW_NUMBER()函数分别应用于每个分区,并重新初始化每个分区的...

    oracle的row_numer()函数的使用

    介绍了 row_number() over(order by column asc) 函数和 row_number() over(partition by column1 order by column2 asc) 的使用实例和方法

    ROW_NUMBER、RANK、DENSE_RANK 和 NTILE

    以下查询通过使用 ROW_NUMBER 函数并指定 OVER (ORDER BY score DESC) 生成所需的结果: ``` SELECT ROW_NUMBER() OVER(ORDER BY score DESC) AS rownum, speaker, track, score FROM SpeakerStats ``` rownum ...

    RANK OVER()和ROW_NUMBER()OVER的使用

    介绍rank() over()分析函数和 row_number() over 的使用实例及其异同点

    SQL2005 四个排名函数(row_number、rank、dense_rank和ntile)的比较

    - `row_number`:为每一行生成一个唯一的序号,不受相同值的影响。 - `rank`:在考虑相同值的情况下分配序号,出现相同值时跳过序号。 - `dense_rank`:同样考虑相同值,但保证序号的连续性,不会跳过序号。 - `...

    row_number

    ### row_number() 函数详解及应用 #### 一、row_number()函数介绍 `row_number()` 是 SQL 中的一个窗口函数,常用于为查询结果中的每一行分配一个唯一且连续的整数编号。这个函数通常与 `OVER()` 子句一起使用来...

    Mssql 增加排序列,分组排序与普通排序 ROW_NUMBER.docx

    在Mssql中,`ROW_NUMBER()` 可以与 `OVER` 子句一起使用,来指定排序和分组规则。 1. **`ROW_NUMBER()` 语法**: `ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) AS Seq` - `PARTITION BY` 子句用于将数据...

    深入探讨:oracle中row_number() over()分析函数用法

    Oracle数据库中的`row_number() over()`分析函数是一个非常实用的工具,用于为数据集中的每一行分配一个唯一的整数,这个数字基于指定的排序条件。在处理大数据集时,它可以帮助我们进行分页、排名或者在复杂的查询...

    Row_number 分页存储过程

    例如,你可以创建一个名为`Pager_Rownumber`的存储过程,如下所示: ```sql CREATE PROCEDURE Pager_Rownumber @PageNumber INT, @PageSize INT, @OrderColumn NVARCHAR(128), @TableName NVARCHAR(128) AS ...

Global site tag (gtag.js) - Google Analytics