2

我正在使用 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;

该查询返回一个计算字段 [movement],它是 [Allocation] 的连续值的增加或减少。

我已包含此查询返回的数据的屏幕截图。

返回数据截图

但是,查询尚未完成。我需要修改语句,以便比较的 [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) 

但这会导致大量数据行重复。

有人可以建议如何比较 [Allocation] 的连续值,但只能在具有匹配 [FeeEarner] 和 [CaseNo] 的数据行之间进行比较吗?

注意- 我不能使用 LAG,因为我的客户使用的是不支持并行数据仓库的 SQL Server 2008 R2。

4

3 回答 3

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
于 2013-02-07T16:02:39.287 回答
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 byrow_number()通话中。

此外,如果您使用的是 Oracle、SQL Server 2012、较新版本的 DB2 或 Postgres,那么lead()/lag()函数将是更好的选择。

于 2013-02-07T15:59:00.857 回答
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
于 2013-02-07T16:52:08.963 回答