排名&找到同一列

时间:2016-08-05 20:03:08

标签: sql sql-server ranking

我有下表 -

enter image description here

在这里,我使用由audit_date排序的case_identifier分区的rank函数创建了“Order”列。

现在,我想创建一个新列 -

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

你能帮我解释一下语法吗?感谢。

4 个答案:

答案 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也可以正常工作,但是要么这样做。