update orders
set tname = (select top 1 t.task
from task t
where prod_typ='2' and sorder_nbr = t.ORDER_NBR
order by t.strt_dt desc)
where Prod_type='2'
update orders
set tname= (select top 1 t.task
from task t
where prod_typ='1' and sorder_nbr=t.ORDER_NBR
order by t.strt_dt desc)
where Prod_type='1'
我正在尝试通过tname
表中的最新任务更新orders
表的task
列
prod_typ
表的orders
条件为1,sorder_nbr
表的orders
和task
表的order_nbr相等
我的第一个更新语句适用于行为900k的行,第二个更新行为400k表示第二个更新语句需要一个多小时才能运行,最后我取消了查询
答案 0 :(得分:3)
1)您查询和我的查询:
update orders
set tname = (select top 1 t.task
from task t
where prod_type='2' and order_nbr = t.ORDER_NBR
order by t.strt_dt desc)
where Prod_type='2';
go
update o
set tname = (select top 1 t.task
from task t
where prod_type='2' and o.order_nbr = t.ORDER_NBR
order by t.strt_dt desc)
from dbo.orders o
where Prod_type='2';
go
实际执行计划:
如您所见,如果当前数据库的默认排序规则为CI(不区分大小写),则跟随谓词order_nbr=t.ORDER_NBR
强制SQL Server将t.ORDER_NBR
的值与值order_nbr
列进行比较来自同一张表task t
。查看与第一个查询对应的第一个执行计划。
要解决 这个问题,我已经使用了另一个别名
dbo.orders o
我已经重新确定谓词o.order_nbr = t.ORDER_NBR
。您也可以在第二个执行计划中看到这一点。
取决于每个order_num和&的任务数量。 prod_type你可以测试S#1,如果有很多任务,或S#2,如果每个order_num& prod_type。同样,您需要使用您的数据进行测试,以确定哪种解决方案更好。
2)解决方案#1:
UPDATE o
SET tname =
COALESCE(
(SELECT TOP(1) t.task
FROM dbo.task t
WHERE t.prod_type=o.Prod_type
AND o.order_nbr = t.ORDER_NBR
ORDER BY t.strt_dt DESC), tname
)
FROM dbo.orders o
WHERE o.Prod_type IN ('1', '2');
3)解决方案#2:
UPDATE o
SET tname = lt.task
FROM dbo.orders o
INNER JOIN
(
SELECT src.order_nbr, src.prod_type, src.task
FROM (
SELECT t.ORDER_NBR, t.prod_type, t.task,
ROW_NUMBER() OVER(PARTITION BY t.ORDER_NBR, t.prod_type ORDER BY t.strt_dt DESC) RowNum
FROM dbo.task t
) src
WHERE src.RowNum = 1
) lt -- last task
ON o.order_nbr = lt.ORDER_NBR AND o.prod_type = lt.prod_type
WHERE o.Prod_type IN ('1', '2');
如果您有疑问,请随时提出。
4)dbo.task(order_nbr, prod_type, strt_dt) include (task)
上的索引应该有助于两种解决方案。
5)你也应该公布实际的执行计划。
答案 1 :(得分:1)
尝试这样的事情。这将同时更新prod_type为1和2。
UPDATE orders
SET tname = t1.task
FROM orders o
CROSS APPLY (
SELECT order_nbr, prod_type, t.task, row_number() OVER (PARTITION BY order_nbr, prod_type ORDER BY strt_dt DESC) rownumber
FROM task t
WHERE o.prod_type = t.prod_type
AND o.order_nbr = t.order_nbr) t1
WHERE t1.rownumber = 1
AND o.prod_type in (1,2)
答案 2 :(得分:1)
如果数据大小比我建议您使用变量更新表,或使用CTE更新
Update a table using CTE and NEWID()
我希望这会有所帮助
用tname(t.task)作为 (选择前1个t.task 来自任务t 其中prod_typ ='2',order_nbr = t.ORDER_NBR 按t.strt_dt desc排序 插入订单(t.task)
答案 3 :(得分:-1)
使用CTE查询会加快这一点,因为不需要为每一行创建子查询,而是预先准备好。这是sqlfiddle
;with cteTaskNames as
(
select top 1 t.task
from task t
where prod_type='2' and order_nbr=t.ORDER_NBR
order by t.strt_dt desc
)
update orders
set tname = (select task from cteTaskNames)
where Prod_type='2'
go
另外, 1)“prod_type”是整数字段还是字符串字段? 2)如果在cte中添加group by,则可以对订单执行内部联接,并使用cte查询立即运行所有更新,而不是执行每个查询。