如何使用 ROW_NUMBER()?

Posted

技术标签:

【中文标题】如何使用 ROW_NUMBER()?【英文标题】:How do I use ROW_NUMBER()? 【发布时间】:2010-10-31 22:52:24 【问题描述】:

我想使用ROW_NUMBER() 获取...

    获取max(ROW_NUMBER()) --> 或者我猜这也是所有行的计数

我试过了:

SELECT max(ROW_NUMBER() OVER(ORDER BY UserId)) FROM Users

但它似乎没有工作......

    使用给定的信息获取ROW_NUMBER(),即。如果我有一个名字并且我想知道这个名字来自哪一行。

我认为这与我为 #1 尝试的类似

SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'

但这也没有用...

有什么想法吗?

【问题讨论】:

【参考方案1】:

对于第一个问题,为什么不直接使用?

SELECT COUNT(*) FROM myTable 

获取计数。

对于第二个问题,行的主键是用来标识特定行的。不要尝试使用行号。


如果您在主查询中返回 Row_Number(),

SELECT ROW_NUMBER() OVER (Order by Id) AS RowNumber, Field1, Field2, Field3
FROM User

然后当您想返回 5 行时,您可以获取当前行号并使用以下查询来确定当前行 -5 的行

SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
     FROM User ) us 
WHERE Row = CurrentRow - 5   

【讨论】:

在我的情况下,我得到了一个 UserId,我想获得一定数量的行数的 UserId。如果一行被删除怎么办?在这种情况下,我不能只使用 UserId - offset,因为那样我就不会得到正确的记录。 最好使用 select count(1) from mytable 来选择记录数。如此快速高效【参考方案2】:

虽然我同意其他人的观点,您可以使用 count() 来获取总行数,但这里是您可以使用 row_count() 的方法:

    获取总行数:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp

    获取名称为 Matt 的行号:

    with temp as (
        select name, row_number() over (order by id) as rownum
        from table_name
    )
    select rownum from temp where name like 'Matt'

您可以进一步使用min(rownum)max(rownum) 分别获取Matt 的第一行或最后一行。

这些是row_number() 的非常简单的实现。您可以将其用于更复杂的分组。查看我对Advanced grouping without using a sub query的回复

【讨论】:

能否请您解释一下如何选择列,用于order by X?也就是说,X应该如何确定?谢谢! @KevinMeredith:order by X 是您将用来确定行分配ROW_NUMBERS() 的顺序的顺序。请记住,关系数据库中的表,尽管它们的名称,没有正式的排序,所以如果你想调用一行“1”或“10”或“1337”,你需要先使用ORDER BY 对它们进行排序子句,这是 OVER (ORDER BY X) 子句中的那个。【参考方案3】:

如果您需要返回表的总行数,您可以使用SELECT COUNT(*) 语句的替代方式。

因为SELECT COUNT(*) 进行全表扫描以返回行数,所以对于大表可能需要很长时间。在这种情况下,您可以改用sysindexes 系统表。有一个 ROWS 列包含数据库中每个表的总行数。您可以使用以下选择语句:

SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2

这将大大减少您的查询时间。

【讨论】:

您对全表扫描的看法是正确的,但请注意,它不一定是聚集索引扫描,因为它可能会为此使用非聚集索引 这仅适用于 Sql-Server,因为其他 RDMBS 已经优化了选择计数【参考方案4】:

您可以使用它来获取第一个记录 where has 子句

SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum 
FROM     Users 
WHERE    UserName = 'Joe'
ORDER BY rownum ASC

【讨论】:

【参考方案5】:

ROW_NUMBER() 为从 1 开始的每一行返回一个唯一编号。您只需编写以下代码即可轻松使用:

ROW_NUMBER() OVER (ORDER BY 'Column_Name' DESC) as ROW_NUMBER

【讨论】:

【参考方案6】:

可能与这里的问题无关。但我发现在使用 ROW_NUMBER 时它可能很有用 -

SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID 
FROM #Any_Table

【讨论】:

【参考方案7】:
select 
  Ml.Hid,
  ml.blockid,
  row_number() over (partition by ml.blockid order by Ml.Hid desc) as rownumber,
  H.HNAME 
from MIT_LeadBechmarkHamletwise ML
join [MT.HAMLE] h on ML.Hid=h.HID

【讨论】:

【参考方案8】:
SELECT num, UserName FROM 
 (SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
  From Users) AS numbered
WHERE UserName='Joe'

【讨论】:

枚举所有行——否则你只是在枚举用户名是Joe的行,这不是目标;-)。 @Matt:叫我学究;我倾向于“派生表”或“匿名视图”而不是“子选择”一词。 @adam,因为我也是一个书呆子——“嵌套选择”会让你更快乐吗?当没有 TABLEVIEW 关键字时,我不喜欢使用诸如 table 或 view 之类的术语......但 SELECT 肯定是!-) @Alex:你提出了一个有效的观点。 “嵌套选择”对我很有用 :) 顺便说一句,我真的很喜欢阅读您添加到 cmets 和答案中的轶事。 @Adam,谢谢!有时我的答案是非常简单的代码,就像这里一样,但是当我有空闲时间时,我确实喜欢充实它们;-)。【参考方案9】:

如果您绝对想为此使用 ROW_NUMBER(而不是 count(*)),您可以随时使用:

SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)   
FROM USERS  
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC

【讨论】:

【参考方案10】:

限制查询结果可以使用Row_Number

例子:

SELECT * FROM (
    select row_number() OVER (order by createtime desc) AS ROWINDEX,* 
    from TABLENAME ) TB
WHERE TB.ROWINDEX between 0 and 10

-- 通过上述查询,我​​将获得来自TABLENAME 的结果的第 1 页。

【讨论】:

【参考方案11】:

需要使用WITH table AS创建虚拟表,在给定的查询中提到。

通过使用此虚拟表,您可以执行 w.r.t row_number 的 CRUD 操作。

查询:

WITH table AS
-
(SELECT row_number() OVER(ORDER BY UserId) rn, * FROM Users)
-
SELECT * FROM table WHERE UserName='Joe'
-

尽管SELECT,你可以在最后一句中使用INSERTUPDATEDELETE

【讨论】:

【参考方案12】:

SQL Row_Number() function是对相关记录集中的数据行进行排序和分配订单号。所以它用于对行进行编号,例如识别订单金额最高的前10行或识别每个客户的订单金额最高等。

如果您想对数据集进行排序并通过将它们分成类别来为每行编号,我们使用带有 Partition By 子句的 Row_Number()。例如,对每个客户的订单进行排序,其中数据集包含所有订单等。

SELECT
    SalesOrderNumber,
    CustomerId,
    SubTotal,
    ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SubTotal DESC) rn
FROM Sales.SalesOrderHeader

但据我了解,您想计算按列分组的行数。为了可视化需求,如果您想将相关客户的所有订单计数作为除订单信息之外的单独列查看,您可以使用COUNT() aggregation function with Partition By clause

例如,

SELECT
    SalesOrderNumber,
    CustomerId,
    COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader

【讨论】:

【参考方案13】:

这个查询:

SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'

将返回UserName'Joe' 的所有行,除非您没有UserName='Joe'

它们将按UserID 的顺序列出,row_number 字段将从 1 开始并递增,但是许多行包含 UserName='Joe'

如果它对您不起作用,那么您的 WHERE 命令有问题,或者表中没有 UserID。检查 UserIDUserName 两个字段的拼写。

【讨论】:

以上是关于如何使用 ROW_NUMBER()?的主要内容,如果未能解决你的问题,请参考以下文章

Row_number() 和 group by 一起不起作用

在某个时间段查找某连续出现问题

当它们包含 ROW_NUMBER() 时,JDBC-driver / SQL Server 总是重新编译我准备好的语句

EXCEL中INDEX怎么使用

带有 Row_Num 的 CASE

如何使用 ROW_NUMBER()?