我正在使用SQL语句来比较字段[Allocation]的连续值,如下所示:
;WITH cteMain AS
(SELECT AllocID, CaseNo, FeeEarner, Allocation, ROW_NUMBER() OVER (ORDER BY AllocID) AS sn
FROM tblAllocations)
SELECT m.AllocID, m.CaseNo, m.FeeEarner, m.Allocation,
ISNULL(sLag.Allocation, 0) AS prevAllocation,
(m.Allocation - ISNULL(sLag.Allocation, 0)) AS movement
FROM cteMain AS m
LEFT OUTER JOIN cteMain AS sLag
ON sLag.sn = m.sn-1;
查询返回计算字段[移动],即[分配]的连续值的增加或减少。
我已经包含了此查询返回的数据的屏幕截图。
但是查询尚未完成。我需要修改语句,以便比较[Allocation]的连续值由[FeeEarner]和[CaseNo]分组/分区。
例如,在数据的第18行,[Allocation]为800,并与之前的600值进行比较。但之前的值属于不同的[CaseNo],即6而不是31.事实上[FeeEarner] ]'PJW'在[CaseNo]'31'之前没有[Allocation],因此[prevAllocation]应该是来自ISNULL关键字的'0'。
我尝试过更改
OVER (ORDER BY AllocID)
到
OVER (PARTITION BY CaseNo, FeeEarner ORDER BY AllocID)
但这会导致大量数据被重复。
有人可以建议如何比较[分配]的连续值,但只能在匹配[FeeEarner]和[CaseNo]的数据行之间进行比较吗?
注意 - 我无法使用LAG,因为我的客户使用的是不支持并行数据仓库的SQL Server 2008 R2。
答案 0 :(得分:3)
我相信你很亲密。试试这个(注意join子句中添加的部分以匹配分区 - 如果没有这个,你将匹配每个第3行,每行第2行跨越分区,这就是你所看到的):
;WITH cteMain AS
(
SELECT AllocID, CaseNo, FeeEarner, Allocation,
ROW_NUMBER() OVER (PARTITION BY CaseNo, FeeEarner ORDER BY AllocID) AS sn
FROM tblAllocations
)
SELECT m.AllocID, m.CaseNo, m.FeeEarner, m.Allocation,
ISNULL(sLag.Allocation, 0) AS prevAllocation,
(m.Allocation - ISNULL(sLag.Allocation, 0)) AS movement
FROM cteMain AS m
LEFT OUTER JOIN cteMain AS sLag
ON sLag.CaseNo = m.CaseNo
AND sLag.FeeEarner = m.FeeEarner
AND sLag.sn = m.sn-1
答案 1 :(得分:0)
您还需要更改加入条件:
FROM cteMain m LEFT OUTER JOIN
cteMain sLag
ON sLag.sn = m.sn-1 and sLag.FeeEarner = m.FeeEarner and slag.CaseNo = m.CaseNo
此外,order by
来电时,您应该只有一个row_number()
。
此外,如果您使用的是Oracle,SQL Server 2012,更新版本的DB2或Postgres,那么lead()
/ lag()
函数将是更好的选择。
答案 2 :(得分:0)
使用OUTER APPLY和EXISTS
的另一个选项SELECT t1.AllocID, t1.CaseNo, t1.FreeEarner, t1.Allocation,
ISNULL(o.Allocation, 0) AS PrevAllocation,
(t1.Allocation - ISNULL(o.Allocation, 0)) AS movement
FROM tblAllocations t1
OUTER APPLY (
SELECT t2.AllocID, t2.CaseNo, t2.FreeEarner, t2.Allocation
FROM tblAllocations t2
WHERE EXISTS (
SELECT 1
FROM tblAllocations t3
WHERE t1.AllocID > t3.AllocID
HAVING MAX(t3.AllocID) = t2.AllocID
) AND t1.CaseNo = t2.CaseNo
) o