2016-08-05 54 views
1

的差值我有如下表 -等級和找到在同一列

enter image description here

在這裏,我已經通過使用case_identifier通過audit_date有序分區排名函數創建的「訂單」一欄。

現在,我想下面創建一個新列 -

enter image description here

新列將是邏輯 -

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 

能否請你幫我的語法?謝謝。

+1

哪個版本的sql server? – techspider

+0

可能重複[如何減去sql中的前一行?](http://stackoverflow.com/questions/17560829/how-can-i-subtract-a-previous-row-in-sql) – techspider

+0

使用Sql Server 2014.謝謝。 – 0nir

回答

1

LAG方法

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服務器,但要麼會。

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] 
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語句的使用聚結。這可能更快,但我覺得這更清楚。

如果您運行並查看執行計劃,它們是相同的。

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 
相關問題