T-SQL更新每组的前n行,每组有n个变量(交叉应用替代)

时间:2016-07-13 18:12:26

标签: sql sql-server tsql

我有两个表 - SourceTable和DestTable - Source包含RowNum和Col的列。我想在Col上加入两个表,然后更新top' n' DestTable的行,其中' n'是SourceTable中RowNum的值。我可以通过交叉申请来做到这一点,但需要几个小时。我正在寻找另一种编写此查询的方法。

My Cross Apply解决方案是 -

UPDATE t 
SET    dest = source 
FROM   #sourcetable s 
       CROSS apply (SELECT TOP(s.rownum) * 
                    FROM   #desttable d 
                    WHERE  d.col = s.col) t 

以下是样本数据 -

SourceTable -

Col, Source, RowNum    
11 , 111   , 2    
12 , 222   , 1

DestTable(更新前) -

Id, Col, Dest    
1 , 11 , 0
2 , 11 , 0
3 , 11 , 0    
4 , 12 , 0    
5 , 12 , 0

DestTable(更新后) -

Id, Col, Dest    
1, 11, 111    
2, 11, 111    
3, 11, 0    
4, 12, 222    
5, 12, 0

但这表现得非常差(即使在正确索引的表上,当行数为几百万且列接近400时需要数小时)。

是否有更有效的方法来编写此查询?

更新 - 实际表结构如下 -

DestTable (包含大约1百万条记录,每个列都已填充) - 38个日期时间,66个浮点数,31个int,210个varchar(50)字段

可输入(它是在相关sql运行之前创建的临时表,包含大约100k条记录并且每列都已填充) - 总共16个字段(4个int,2个datetime,1个float ,rest varchar(50))

索引 - 我无法创建包含所有必填字段的覆盖索引,因为它们因查询而异。我尝试在各种字段组合上创建索引,发现更新运行速度明显更快,没有任何索引。

当前测试结果(行数在DestTable中) -

1000行(没有任何索引) - 05:00分钟

10000行(没有任何索引) - 17:38分钟

100000行(没有任何索引) - 3小时7分钟

100000(4个字段上有任何索引) - 超过7个小时我不得不停止它

1 个答案:

答案 0 :(得分:2)

您可以尝试使用简单的JOIN代替相关的子查询:

WITH cte AS
(
 SELECT d.id, d.col, d.dest, s.source
 FROM (SELECT *,
       rn = ROW_NUMBER() OVER(PARTITION BY col ORDER BY id) FROM #desttable) d
 JOIN #sourcetable s
   ON d.col = s.col
  AND d.rn <= s.rownum 
)
UPDATE cte
SET dest = source;

SELECT *
FROM #desttable;

LiveDemo

您应该发布您的真实数据样本,数据结构和查询计划。否则我们只能猜测如何改进它。