我有下表 -
在这里,我使用由audit_date排序的case_identifier分区的rank函数创建了“Order”列。
现在,我想创建一个新列 -
新专栏的逻辑是 -
select *,
case when [order] = '1' then [days_diff]
else (val of [days_diff] in rank 2) - (val of [days_diff] in rank 1) ...
end as '[New_Col]'
from TABLE
你能帮我解释一下语法吗?感谢。
答案 0 :(得分:3)
看看LAG功能。它将为您提供您想要的东西。
类似的东西:
declare @temptable TABLE (case_id varchar(2), row_order int, days_diff float)
INSERT INTO @temptable values ('A',1,5)
INSERT INTO @temptable values ('A',2,3)
INSERT INTO @temptable values ('A',3,2)
INSERT INTO @temptable values ('B',1,5)
INSERT INTO @temptable values ('B',2,1)
--select * from @temptable
SELECT case_id,row_order, LAG(days_diff,1) OVER (PARTITION BY case_id ORDER BY row_order) AS prev_row,days_diff,
CASE
WHEN row_order = 1 THEN days_diff
ELSE LAG(days_diff,1) OVER (PARTITION BY case_id ORDER BY row_order) - days_diff
END AS newcolumn
FROM @temptable
order by case_id,row_order asc
SELECT case_id,row_order,LAG(days_diff,1) OVER (PARTITION BY case_id ORDER BY row_order) AS prev_row, days_diff,
COALESCE(LAG(days_diff,1) OVER (PARTITION BY case_id ORDER BY row_order) - days_diff , days_diff)
FROM @temptable
order by case_id,row_order asc
其他答案将使用合并来代替CASE声明。它可能更快,但我觉得这更清楚。
如果你同时运行并查看执行计划,它们是相同的。
答案 1 :(得分:2)
我相信以下查询可以为您提供所需内容。
SELECT a.*,
'NEW DAYS DIFF' =
CASE
WHEN a.[order] = 1 THEN a.days_diff
ELSE a.days_diff - b.days_diff
END
FROM dbo.tblCaseDaysDiff a
INNER JOIN dbo.tblCaseDaysDiff b
ON
(b.CASE_ID = a.CASE_ID AND b.[order] + 1 = a.[order] ) -- Get the current row and compare with the next highest order
OR (b.CASE_ID = a.CASE_ID AND b.[order] = 1 AND a.[order] = 1) --WHEN ORDER = 1 Get days_diff value
ORDER BY a.CASE_ID, a.[order]
答案 2 :(得分:2)
碰巧,你已经深入了解了窗口函数,正如其他人所指出的那样,LAG会做到这一点。但是,一般情况下,您可以通过创建一行来获得两行的差异:通过将表连接到自身。
with T (CASE_IDENTIFIER, AUDIT_DATE, order, days_diff)
as (
... your query ...
)
select a.*,
a.days_diff - coalesce(b.days_diff, 0) as delta_days_diff
from T as a left join T as b
on a.CASE_IDENTIFIER = b.CASE_IDENTIFIER
and b.days_diff = a.days_diff - 1
答案 3 :(得分:1)
LAG METHOD
SELECT
CASE_IDENTIFIER
,AUDIT_DATE
,[order]
,days_diff
,days_diff - ISNULL(LAG(days_diff,1) OVER (PARTITION BY CASE_IDENTIFIER ORDER BY [order]),0) AS New_Column
FROM @Table
自我加入方法
SELECT
t1.CASE_IDENTIFIER
,AUDIT_DATE
,t1.[order]
,t1.days_diff
,t1.days_diff - ISNULL(t2.days_diff,0) AS New_Column
FROM
@Table t1
LEFT JOIN @Table t2
ON t1.CASE_IDENTIFIER = t2.CASE_IDENTIFIER
AND t1.[order] - 1 = t2.[order]
我觉得很多其他答案都在正确的轨道上,但是有一些细微差别或更简单的方式来写一些。或者也有一些答案提供了写入方向,但是它们的连接或语法有问题。无论如何,无论您使用CASE STATEMENT
方法的LAG,都不需要SELF JOIN
。下一个COALESCE()
很棒,但你只是比较2个值,所以ISNULL()
对sql-server也可以正常工作,但是要么这样做。