在 SQL SERVER 中使用交叉应用进行更新
Posted
技术标签:
【中文标题】在 SQL SERVER 中使用交叉应用进行更新【英文标题】:Update with cross apply in SQL SERVER 【发布时间】:2017-03-21 13:10:04 【问题描述】:我在#def 中有这样的表格:
#def table 我只想计算当前期间“201702”的每个服务订单之间的天数。 Reservice = 0 表示之前未进行过维修。每次再服务时,再服务的计数都会增加。
select
s1.period,
,s1.company
,s1.prod
,s1.id1
,S1.id2
,s1.serv_date
,t.last_servdate
,datediff(dd, ISNULL(T.last_servdate, s1.[serv_Date]),s1.serv_date)AS [Days Since last] from #def s1
Outer apply(
select
top 1 serv_date as last_servdate from #def s2
where s1.prod=s2.prod and s1.id1 =s2.id1
and s1.id2=s2.id2 and s1.company =s2.company
and s2.reservice = s1.reservice-1 and s1.company =’abc’
and s2.company =’abc’)T
where s1.company_code =’abc’ and s1.period ='201702'
update s1
set days_btwn_service = datediff(dd, ISNULL(T.last_servdate,s1.serv_Date]),s1.serv_date) from #def s1
Outer apply(
select top 1 serv_date as last_servdate from #def s2
where s1.prod=s2.prod
and s1.id1 =s2.id1
and s1.id2=s2.id2
and s1.company =s2.company
and s2.reservice = s1.reservice-1
and s1.company =’abc’
and s2.company =’abc’
)T where s1.company_code =’abc’ and s1.period ='201702'
上面的SELECT
查询给了我想要的结果。奇怪的是,在同一个查询中使用 UPDATE
语句根本不会给出想要的结果,但只有很少的行被更新了值。我不知道为什么?!
def 包含已服务多次的所有订单的列表。
编辑:根据@sqlzim 的回复,我更改了查询。他的回复也给出了同样的答案。
【问题讨论】:
左对齐 SQL...很难阅读... 请添加一些示例表数据和预期结果 - 以及格式化文本。同时向我们展示您当前的查询尝试 【参考方案1】:这看起来像 sql-server,所以这个答案是针对 sql-server 的。
我不明白为什么您会从这些查询中得到两个不同的结果,但如果您使用 select
语句得到正确的结果,您可以使用 @987654325 将其放入 common table expression 和 update
@。
serv_date
可以为空吗?如果不是,那么T.serv_date
不能为空,除非您使用outer apply()
而不是cross apply()
。
;with cte as (
select
s1.ord_id
, s1.period
, s1.company
, s1.prod
, s1.id1
, S1.id2
, s1.serv_date
, s1.days_btwn_service
, t.last_servdate
, datediff(day,isnull(T.last_servdate,s1.[serv_Date]),s1.serv_date) as [Days_Since_Last]
from #def s1
cross apply (
select top 1 serv_date as last_servdate
from #def s2
where s1.prod = s2.prod
and s1.id1 = s2.id1
and s1.id2 = s2.id2
and s1.company = s2.company
and s2.reservice = s1.reservice - 1
) T
where s1.company_code = 'abc'
and s1.period = '201702'
)
--select * from cte;
update cte
set days_btwn_service = [Days_Since_Last];
/* This will update the underlying table #def */
/* -- Alternate version
update d
set d.days_btwn_service = cte.[Days_Since_Last]
from #def d join cte on cte.ord_id=d.ord_id
--*/
检查select
的结果,如果正确,运行update
而不是select
。
【讨论】:
@JohnCappelletti 主要来自记事本++中的“Poor Man's T-Sql Formatter” 你有一个错字,它是notepad++ ;) -- 无论如何在 Windows 上。 @SqlZim,CTE!是的!谢谢你。 CTE 更新是否会级联到临时表?选择工作得非常好。更新仍然是个问题。 @JohnCappelletti 我同意我应该更好地格式化它。我不擅长格式化,但我想学习。 SqlZim 的代码可读性很好。下次我会处理的。 :) @SqlZim 还有一个字段 order_id 可以根据 cte 结果唯一标识要更新的行。像这样的东西,但这不起作用 - update d set d.days_btwn_service = [Days since last] from #def d join cte on cte.ord_id=d.ord_id以上是关于在 SQL SERVER 中使用交叉应用进行更新的主要内容,如果未能解决你的问题,请参考以下文章