LAG/LEAD 相当于分组(SQL Server 2008 R2)
LAG/LEAD equivalent with grouping (SQL Server 2008 R2)
注意:我使用的是 SQL Server 2008 R2,内置 LEAD/LAG 功能不可用。
我需要更新 table 的列以包含 ProductID 的 'previous' 和 'next' 值 - table 需要存储 PrevProductID (LAG), ProductID 和 NextProductID (LEAD)。下面的代码很好地做到了这一点,并改编自 Geri Reshef 对 http://blog.sqlauthority.com/2011/11/24/sql-server-solution-to-puzzle-simulate-lead-and-lag-without-using-sql-server-2012-analytic-function/
的回答
USE AdventureWorks2008R2
GO
WITH T1 AS
( SELECT Row_Number() OVER(ORDER BY SalesOrderID,ProductID) N,
s.SalesOrderID,
s.ProductID
FROM Sales.SalesOrderDetail s
WHERE SalesOrderID IN (43670, 43667, 43663)
)
SELECT SalesOrderID,
CASE WHEN N%2=1
THEN MAX(CASE WHEN N%2=0
THEN ProductID
END) OVER (Partition BY N/2)
ELSE MAX(CASE WHEN N%2=1
THEN ProductID
END) OVER (Partition BY (N+1)/2)
END PrevProductID,
ProductID,
CASE WHEN N%2=1
THEN MAX(CASE WHEN N%2=0
THEN ProductID
END) OVER (Partition BY (N+1)/2)
ELSE MAX(CASE
WHEN N%2=1 THEN ProductID
END) OVER (Partition BY N/2)
END NextProductID
FROM T1
ORDER BY
t1.SalesOrderID,
t1.ProductID
这些是结果,Lag/Lead 应用于所有行。
SalesOrderID PrevProductID ProductID NextProductID
------------ ------------- ----------- -------------
43663 NULL 760 710
43667 760 710 773
43667 710 773 775
43667 773 775 778
43667 775 778 709
43670 778 709 710
43670 709 710 773
43670 710 773 776
43670 773 776 NULL
我需要做的是按 SalesOrderID 对 Lag/Lead 值进行分组,在 SalesOrderID 组中,第一次出现指向 NULL 的滞后,最后一次出现指向 NULL 的引导。
SalesOrderID PrevProductID ProductID NextProductID
------------ ------------- ----------- -------------
43663 NULL 760 NULL
43667 NULL 710 773
43667 710 773 775
43667 773 775 778
43667 775 778 NULL
43670 NULL 709 710
43670 709 710 773
43670 710 773 776
43670 773 776 NULL
您只需将 SalesOrderID
添加到查询中的每个 PARTITION BY
子句中即可(ROW_NUMBER() OVER()
,然后是 4 x MAX() OVER()
):
WITH T1 AS
( SELECT SalesOrderID,
ProductID,
N = ROW_NUMBER() OVER(PARTITION BY SalesOrderID ORDER BY SalesOrderID, ProductID)
FROM (VALUES
(43663, 760), (43667, 710), (43667, 773), (43667, 775), (43667, 778),
(43670, 709), (43670, 710), (43670, 773), (43670, 776),
(43680, 1), (43680, 2), (43680, 3), (43680, 4), (43680, 5),
(43680, 6), (43680, 7), (43680, 8), (43680, 9), (43680, 10),
(43681, 1), (43681, 2), (43681, 3), (43681, 4), (43681, 5),
(43681, 6), (43681, 7), (43681, 8), (43681, 9), (43681, 10)
) x (SalesOrderID, ProductID)
)
SELECT T1.SalesOrderID,
PrevProductID = CASE WHEN N % 2 = 1
THEN MAX(CASE WHEN N % 2 = 0 THEN T1.ProductID END)
OVER(PARTITION BY T1.SalesOrderID, N / 2)
ELSE
MAX(CASE WHEN N % 2 = 1 THEN ProductID END)
OVER(PARTITION BY T1.SalesOrderID, (N + 1) / 2)
END,
T1.ProductID,
NextProductID = CASE WHEN N % 2 = 1
THEN MAX(CASE WHEN N % 2 = 0 THEN T1.ProductID END)
OVER(PARTITION BY T1.SalesOrderID, (N + 1) / 2)
ELSE
MAX(CASE WHEN N % 2 = 1 THEN ProductID END)
OVER(PARTITION BY T1.SalesOrderID, N / 2)
END
FROM T1;
其中(不包括我为进一步测试添加的额外行)产生:
SalesOrderID PrevProductID ProductID NextProductID
---------------------------------------------------------------
43663 NULL 760 NULL
43667 NULL 710 773
43667 710 773 775
43667 773 775 778
43667 775 778 NULL
43670 NULL 709 710
43670 709 710 773
43670 710 773 776
43670 773 776 NULL
注意:我使用的是 SQL Server 2008 R2,内置 LEAD/LAG 功能不可用。
我需要更新 table 的列以包含 ProductID 的 'previous' 和 'next' 值 - table 需要存储 PrevProductID (LAG), ProductID 和 NextProductID (LEAD)。下面的代码很好地做到了这一点,并改编自 Geri Reshef 对 http://blog.sqlauthority.com/2011/11/24/sql-server-solution-to-puzzle-simulate-lead-and-lag-without-using-sql-server-2012-analytic-function/
的回答USE AdventureWorks2008R2
GO
WITH T1 AS
( SELECT Row_Number() OVER(ORDER BY SalesOrderID,ProductID) N,
s.SalesOrderID,
s.ProductID
FROM Sales.SalesOrderDetail s
WHERE SalesOrderID IN (43670, 43667, 43663)
)
SELECT SalesOrderID,
CASE WHEN N%2=1
THEN MAX(CASE WHEN N%2=0
THEN ProductID
END) OVER (Partition BY N/2)
ELSE MAX(CASE WHEN N%2=1
THEN ProductID
END) OVER (Partition BY (N+1)/2)
END PrevProductID,
ProductID,
CASE WHEN N%2=1
THEN MAX(CASE WHEN N%2=0
THEN ProductID
END) OVER (Partition BY (N+1)/2)
ELSE MAX(CASE
WHEN N%2=1 THEN ProductID
END) OVER (Partition BY N/2)
END NextProductID
FROM T1
ORDER BY
t1.SalesOrderID,
t1.ProductID
这些是结果,Lag/Lead 应用于所有行。
SalesOrderID PrevProductID ProductID NextProductID
------------ ------------- ----------- -------------
43663 NULL 760 710
43667 760 710 773
43667 710 773 775
43667 773 775 778
43667 775 778 709
43670 778 709 710
43670 709 710 773
43670 710 773 776
43670 773 776 NULL
我需要做的是按 SalesOrderID 对 Lag/Lead 值进行分组,在 SalesOrderID 组中,第一次出现指向 NULL 的滞后,最后一次出现指向 NULL 的引导。
SalesOrderID PrevProductID ProductID NextProductID
------------ ------------- ----------- -------------
43663 NULL 760 NULL
43667 NULL 710 773
43667 710 773 775
43667 773 775 778
43667 775 778 NULL
43670 NULL 709 710
43670 709 710 773
43670 710 773 776
43670 773 776 NULL
您只需将 SalesOrderID
添加到查询中的每个 PARTITION BY
子句中即可(ROW_NUMBER() OVER()
,然后是 4 x MAX() OVER()
):
WITH T1 AS
( SELECT SalesOrderID,
ProductID,
N = ROW_NUMBER() OVER(PARTITION BY SalesOrderID ORDER BY SalesOrderID, ProductID)
FROM (VALUES
(43663, 760), (43667, 710), (43667, 773), (43667, 775), (43667, 778),
(43670, 709), (43670, 710), (43670, 773), (43670, 776),
(43680, 1), (43680, 2), (43680, 3), (43680, 4), (43680, 5),
(43680, 6), (43680, 7), (43680, 8), (43680, 9), (43680, 10),
(43681, 1), (43681, 2), (43681, 3), (43681, 4), (43681, 5),
(43681, 6), (43681, 7), (43681, 8), (43681, 9), (43681, 10)
) x (SalesOrderID, ProductID)
)
SELECT T1.SalesOrderID,
PrevProductID = CASE WHEN N % 2 = 1
THEN MAX(CASE WHEN N % 2 = 0 THEN T1.ProductID END)
OVER(PARTITION BY T1.SalesOrderID, N / 2)
ELSE
MAX(CASE WHEN N % 2 = 1 THEN ProductID END)
OVER(PARTITION BY T1.SalesOrderID, (N + 1) / 2)
END,
T1.ProductID,
NextProductID = CASE WHEN N % 2 = 1
THEN MAX(CASE WHEN N % 2 = 0 THEN T1.ProductID END)
OVER(PARTITION BY T1.SalesOrderID, (N + 1) / 2)
ELSE
MAX(CASE WHEN N % 2 = 1 THEN ProductID END)
OVER(PARTITION BY T1.SalesOrderID, N / 2)
END
FROM T1;
其中(不包括我为进一步测试添加的额外行)产生:
SalesOrderID PrevProductID ProductID NextProductID
---------------------------------------------------------------
43663 NULL 760 NULL
43667 NULL 710 773
43667 710 773 775
43667 773 775 778
43667 775 778 NULL
43670 NULL 709 710
43670 709 710 773
43670 710 773 776
43670 773 776 NULL