SQL Server - 带有 PARTITION 的 ROW_NUMBER(),如何获取多条记录?

Posted

技术标签:

【中文标题】SQL Server - 带有 PARTITION 的 ROW_NUMBER(),如何获取多条记录?【英文标题】:SQL Server - ROW_NUMBER() with PARTITION, how to get multiple records? 【发布时间】:2021-02-12 20:51:06 【问题描述】:

我正在为我的查询而苦苦挣扎

SELECT * FROM (
   SELECT ins.ID, ins.UnitElement_ID, ins.Date, ue.Code, 
          ROW_NUMBER() OVER (PARTITION BY ins.UnitElement_ID ORDER BY ins.Date DESC) AS lastAnomaly
   FROM Inspection ins
   INNER JOIN UnitElement ue ON ins.UnitElement_ID = ue.ID
   INNER JOIN InspectionedAnomaly ia ON ia.Inspection_ID = ins.ID
   WHERE ins.UnitElement_ID IN (3,10)
   AND ins.Evaluation IS NOT NULL
) selectedAnomaly

输出结果是

    ID        UnitElement_ID    Date                  Code       lastAnomaly
0   3020217   3                 2020-10-30 12:09:50   F01001G2   1
1   3020217   3                 2020-10-30 12:09:50   F01001G2   2
2   3020217   3                 2020-10-30 12:09:50   F01001G2   3
3   3009055   10                2020-05-04 00:00:00   F01001M1   1
4   3009055   10                2020-05-04 00:00:00   F01001M1   2
5   3020224   10                2020-05-04 00:00:00   F01001M1   3
6   3020224   10                2020-05-04 00:00:00   F01001M1   4
7   670231    10                2019-07-23 00:00:00   F01001M1   5
8   670231    10                2019-07-23 00:00:00   F01001M1   6
9   576227    10                2018-11-05 00:00:00   F01001M1   7

当我添加 Where 子句 WHERE lastAnomaly = 1 时,它工作得很好,但是当我的日期与“最近”日期相同(例如第 0,1 和 2 行)时,就会出现问题。 如果最近的日期相同,有没有办法提取 sql 查询中的所有 3 行? 谢谢大家

【问题讨论】:

是的,然后使用RANKDENSE_RANK 而不是ROW_NUMBER 使用RANK()DENSE_RANK() 代替ROW_NUMBER() 标记时,请仅标记您真正使用的RDBMS。 mysql 和 SQL Server 是 2 个完全不同的 RDBMS 【参考方案1】:

使用rank() 和过滤:

SELECT *
FROM (SELECT ins.ID, ins.UnitElement_ID, ins.Date, ue.Code, 
             RANK() OVER (PARTITION BY ins.UnitElement_ID ORDER BY ins.Date DESC) AS lastAnomaly
      FROM Inspection ins JOIN
           UnitElement ue
           ON ins.UnitElement_ID = ue.ID JOIN
           InspectionedAnomaly ia
           ON ia.Inspection_ID = ins.ID
      WHERE ins.UnitElement_ID IN (3, 10) AND
            ins.Evaluation IS NOT NULL
     ) sa
WHERE lastAnomaly = 1;

或者,如果您愿意,可以使用MAX()

             MAX(ins.DATE) OVER (PARTITION BY ins.UnitElement_ID) AS lastAnomalyDate
 . . .
 WHERE lastAnomalyDate = DATE

【讨论】:

【参考方案2】:

使用rank() 代替row_number()。它为与OVER() 子句的ORDER BY 关联的行分配相同的排名。

所以:

SELECT * 
FROM (
   SELECT ins.ID, ins.UnitElement_ID, ins.Date, ue.Code, 
          RANK() OVER (PARTITION BY ins.UnitElement_ID ORDER BY ins.Date DESC) AS lastAnomaly
   FROM Inspection ins
   INNER JOIN UnitElement ue ON ins.UnitElement_ID = ue.ID
   INNER JOIN InspectionedAnomaly ia ON ia.Inspection_ID = ins.ID
   WHERE ins.UnitElement_ID IN (3,10)
   AND ins.Evaluation IS NOT NULL
) selectedAnomaly
WHERE lastAnomaly = 1

【讨论】:

以上是关于SQL Server - 带有 PARTITION 的 ROW_NUMBER(),如何获取多条记录?的主要内容,如果未能解决你的问题,请参考以下文章

转载:SQL Server 2008-建立分区表(Table Partition) 转载

SQL Server: Difference between PARTITION BY and GROUP BY

SQL SERVER OVER PARTITION 业务案例

SQL Server:循环遍历每个(PARTITION BY ...)元素的过程或函数

SQL Server 10.50 OVER PARTITION 无法识别

在 sql server 中选择 distinct 和 partition by