Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 更新表:不使用游标或while循环的前几行的摘要_Sql_Sql Server - Fatal编程技术网

Sql 更新表:不使用游标或while循环的前几行的摘要

Sql 更新表:不使用游标或while循环的前几行的摘要,sql,sql-server,Sql,Sql Server,我的表格如下: |ID | UpDown | ContinuesUP | ContinuesDown | ContinuesStop| |---------------------------------------------------------| |1 | 1 | | | | |---------------------------------------------------------| |2

我的表格如下:

|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    |             |               |              |
|---------------------------------------------------------|
我想快速更新表,以基于前两列填充右三列,而无需使用游标或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       |              |
|---------------------------------------------------------|
如有任何意见和建议,将不胜感激

感谢您使用with和gaps and islands样式的解决方案,以及另一个用于计数的解决方案:

;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演示:

返回:

+----+--------+-------------+---------------+---------------+
| 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

您可以使用此查询进行更新

;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

您可以使用LAG分析函数访问前一行的值,在前一行的基础上计算向上/向下投票,然后使用它进行更新,如所述,或者按照SqlZim建议的方式进行更新。然而,对于数百万条记录来说,它仍然是缓慢的,特别是如果你有索引的话

但是,如果您使用短事务并通过相对较小的批(每批1000-10000个)执行此操作,则即使光标也可以快速动作