我有一张表格如下:
|ID | UpDown | ContinuesUP | ContinuesDown | ContinuesStop|
|---------------------------------------------------------|
|1 | 1 | | | |
|---------------------------------------------------------|
|2 | 1 | | | |
|---------------------------------------------------------|
|3 | 1 | | | |
|---------------------------------------------------------|
|4 | -1 | | | |
|---------------------------------------------------------|
|5 | 1 | | | |
|---------------------------------------------------------|
|6 | 0 | | | |
|---------------------------------------------------------|
|7 | -1 | | | |
|---------------------------------------------------------|
|8 | -1 | | | |
|---------------------------------------------------------|
|9 | -1 | | | |
|---------------------------------------------------------|
|10 | -1 | | | |
|---------------------------------------------------------|
|11 | 0 | | | |
|---------------------------------------------------------|
|12 | 0 | | | |
|---------------------------------------------------------|
|13 | 1 | | | |
|---------------------------------------------------------|
|14 | 1 | | | |
|---------------------------------------------------------|
|15 | -1 | | | |
|---------------------------------------------------------|
我想快速更新表,根据前两列填充三个右列,而不使用Cursor或While循环。 我的表有数百万行,当我使用while循环来计算它时需要几个小时。 结果应该是这样的:
|ID | UpDown | ContinuesUP | ContinuesDown | ContinuesStop|
|---------------------------------------------------------|
|1 | 1 | 1 | | |
|---------------------------------------------------------|
|2 | 1 | 2 | | |
|---------------------------------------------------------|
|3 | 1 | 3 | | |
|---------------------------------------------------------|
|4 | -1 | | 1 | |
|---------------------------------------------------------|
|5 | 1 | 1 | | |
|---------------------------------------------------------|
|6 | 0 | | | 1 |
|---------------------------------------------------------|
|7 | -1 | | 1 | |
|---------------------------------------------------------|
|8 | -1 | | 2 | |
|---------------------------------------------------------|
|9 | -1 | | 3 | |
|---------------------------------------------------------|
|10 | -1 | | 4 | |
|---------------------------------------------------------|
|11 | 0 | | | 1 |
|---------------------------------------------------------|
|12 | 0 | | | 2 |
|---------------------------------------------------------|
|13 | 1 | 1 | | |
|---------------------------------------------------------|
|14 | 1 | 2 | | |
|---------------------------------------------------------|
|15 | -1 | | 1 | |
|---------------------------------------------------------|
任何建议和建议将不胜感激
谢谢
答案 0 :(得分:4)
使用带common table expression的row_number()
和差距和岛屿样式解决方案,并使用另一个row_number()
进行计数:
;with cte as (
select
id
, updown
, grp = row_number() over (order by id) - row_number() over (partition by UpDown order by id)
from t
)
select
id
, updown
, ContinuesUp = case when updown = 1 then row_number() over (partition by updown, grp order by id) end
, ContinuesDown = case when updown = -1 then row_number() over (partition by updown, grp order by id) end
, ContinuesStop = case when updown = 0 then row_number() over (partition by updown, grp order by id) end
from cte
order by id
rextester演示:http://rextester.com/KLZ58591
返回:
+----+--------+-------------+---------------+---------------+
| id | updown | ContinuesUp | ContinuesDown | ContinuesStop |
+----+--------+-------------+---------------+---------------+
| 1 | 1 | 1 | NULL | NULL |
| 2 | 1 | 2 | NULL | NULL |
| 3 | 1 | 3 | NULL | NULL |
| 4 | -1 | NULL | 1 | NULL |
| 5 | 1 | 1 | NULL | NULL |
| 6 | 0 | NULL | NULL | 1 |
| 7 | -1 | NULL | 1 | NULL |
| 8 | -1 | NULL | 2 | NULL |
| 9 | -1 | NULL | 3 | NULL |
| 10 | -1 | NULL | 4 | NULL |
| 11 | 0 | NULL | NULL | 1 |
| 12 | 0 | NULL | NULL | 2 |
| 13 | 1 | 1 | NULL | NULL |
| 14 | 1 | 2 | NULL | NULL |
| 15 | -1 | NULL | 1 | NULL |
+----+--------+-------------+---------------+---------------+
作为更新:
;with cte as (
select *
, Continues = row_number() over (partition by updown, grp order by id)
from (
select *
, grp = row_number() over (order by id) - row_number() over (partition by UpDown order by id)
from t
) sub
)
update cte set
ContinuesUp = case when updown = 1 then Continues end
, ContinuesDown = case when updown = -1 then Continues end
, ContinuesStop = case when updown = 0 then Continues end
答案 1 :(得分:1)
您可以使用此查询进行更新。
;WITH T AS
(
select *,
RNID = ROW_NUMBER() OVER( ORDER BY ID)
,RNUpDown = ROW_NUMBER() OVER( PARTITION BY UpDown ORDER BY ID)
from @T
)
,Y AS
(
SELECT *, RN=ROW_NUMBER() OVER(PARTITION BY UpDown,RNID-RNUpDown ORDER BY ID) FROM T
)
UPDATE Y SET
ContinuesUP = CASE WHEN UpDown = 1 THEN RN ELSE ContinuesUP END,
ContinuesDown = CASE WHEN UpDown = -1 THEN RN ELSE ContinuesUP END,
ContinuesStop = CASE WHEN UpDown = 0 THEN RN ELSE ContinuesUP END
答案 2 :(得分:0)
您可以使用LAG分析函数来访问上一行值,在前一行的基础上计算上/下投票,然后使用它来更新,就像它描述的here或者像SqlZim建议的那样。然而,对于数百万条记录来说,它仍然很慢,特别是如果你有索引
但是,如果您使用短交易并通过相对较小的批次(每批1000 - 10000)执行此操作,即使光标也可以快速行动