【发布时间】:2016-05-14 11:47:17
【问题描述】:
如何获得在分区更改时重新启动的 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 行的块,游标在每批 250k 行约 11 分钟内运行并删除行,下面的答案使用 DELETE,每批 250k 行需要约 35 分钟。
【问题讨论】:
-
在您的示例中,您如何区分第一组
value = 1(ids 1 和 2)和第二组(ids 5、6 和 7)? -
我不太明白这个问题。按时间顺序,两者之间还有其他值。
-
@AlinI:每个组中哪些特定行被认为是多余的,这对您来说很重要吗?例如,保留最早的行与每个组中的最新行是否重要?
-
是的,重要的是,最早的行应该保留在表中。
-
您尝试基于
RANK()的窗口函数版本的问题是您想要的分区不是由value列严格确定的,实际上也不是由any 列组合。它们是相对于特定行顺序的行对的函数。正如 Gordon 在他的回答中所建议的那样,lag()和lead()窗口函数正是处理这个问题的方法。
标签: sql sql-server window-functions