sql - RANK() OVER PARTITION 并重置 RANK

标签 sql sql-server window-functions

如何获得在分区更改时重新启动的 RANK? 我有这张表:

ID    Date        Value  
1     2015-01-01  1  
2     2015-01-02  1 <redundant  
3     2015-01-03  2  
4     2015-01-05  2 <redundant  
5     2015-01-06  1  
6     2015-01-08  1 <redundant  
7     2015-01-09  1 <redundant  
8     2015-01-10  2  
9     2015-01-11  3  
10    2015-01-12  3 <redundant  

并且我正在尝试删除上一个条目中值未更改的所有行(标记为<冗余)。 我尝试过使用游标,但它花费的时间太长,因为该表大约有 5000 万行。

我也尝试过使用 RANK:

SELECT ID, Date, Value,
RANK() over(partition by Value order by Date ASC) Rank,
FROM DataLogging 
ORDER BY Date ASC 

但我得到:

ID    Date        Value  Rank   (Rank)
1     2015-01-01  1      1      (1)
2     2015-01-02  1      2      (2)
3     2015-01-03  2      1      (1)
4     2015-01-05  2      2      (2)
5     2015-01-06  1      3      (1)
6     2015-01-08  1      4      (2)
7     2015-01-09  1      5      (3)
8     2015-01-10  2      3      (1)
9     2015-01-11  3      1      (1)
10    2015-01-12  3      2      (2)
括号中的

是我想要的 Rank,这样我就可以过滤掉 Rank = 1 的行并删除其余的行。

编辑:我已经接受了似乎最容易编写的答案,但不幸的是,没有一个答案运行得足够快来删除行。 最后我决定使用CURSOR。我将数据分成大约 250k 行的 block ,游标运行并删除每批 250k 行约 11 分钟的行,下面的答案,使用 DELETE,每批 250k 行约花费 35 分钟。

最佳答案

这是一种有点复杂的方法:

WITH CTE AS
(
    SELECT  *, 
            ROW_NUMBER() OVER(ORDER BY [Date]) RN1,
            ROW_NUMBER() OVER(PARTITION BY Value ORDER BY [Date]) RN2
    FROM dbo.YourTable
), CTE2 AS
(
    SELECT *, ROW_NUMBER() OVER(PARTITION BY Value, RN1 - RN2 ORDER BY [Date]) N
    FROM CTE
)
SELECT *
FROM CTE2
ORDER BY ID;

结果是:

╔════╦════════════╦═══════╦═════╦═════╦═══╗
║ ID ║    Date    ║ Value ║ RN1 ║ RN2 ║ N ║
╠════╬════════════╬═══════╬═════╬═════╬═══╣
║  1 ║ 2015-01-01 ║     1 ║   1 ║   1 ║ 1 ║
║  2 ║ 2015-01-02 ║     1 ║   2 ║   2 ║ 2 ║
║  3 ║ 2015-01-03 ║     2 ║   3 ║   1 ║ 1 ║
║  4 ║ 2015-01-05 ║     2 ║   4 ║   2 ║ 2 ║
║  5 ║ 2015-01-06 ║     1 ║   5 ║   3 ║ 1 ║
║  6 ║ 2015-01-08 ║     1 ║   6 ║   4 ║ 2 ║
║  7 ║ 2015-01-09 ║     1 ║   7 ║   5 ║ 3 ║
║  8 ║ 2015-01-10 ║     2 ║   8 ║   3 ║ 1 ║
║  9 ║ 2015-01-11 ║     3 ║   9 ║   1 ║ 1 ║
║ 10 ║ 2015-01-12 ║     3 ║  10 ║   2 ║ 2 ║
╚════╩════════════╩═══════╩═════╩═════╩═══╝

要删除您不需要的行,您只需执行以下操作:

DELETE FROM CTE2
WHERE N > 1;

关于sql - RANK() OVER PARTITION 并重置 RANK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35208241/

相关文章:

sql-server - 集成安全 = True 和集成安全 = SSPI 之间有什么区别?

sql - 在表格中找到相同地理点的最快方法是什么?

sql - Postgres 使用窗口函数计算差异

sql-server - SQL 中的高效日期比较

c# - Entity Framework 死锁

sql - SQL 的月差

sql - 如何从 t-sql 中的 xml 变量获取节点名称和值

sql - 获取连接表列的不同总和

mysql - 如何选择表中其他表中没有的行

sql - 从列子集计算最小记录版本集