在 T-SQL 中使用 Window 函数计算类别列
Category column calculation with Window function in T-SQL
我的问题很简单,但我找不到解决方案 - 可能使用 window 函数,我有以下示例数据:
ID OrderDate TotalOrder
--------------------------
1 2019-01-01 5
2 2019-01-02 3
3 2019-01-03 1
4 2019-01-04 15
5 2019-01-05 20
6 2019-01-06 18
7 2019-01-07 2
8 2019-01-08 4
9 2019-01-09 9
要求的结果是:
ID OrderDate TotalOrder Category
-------------------------------------
1 2019-01-01 5 1
2 2019-01-02 3 1
3 2019-01-03 1 1
4 2019-01-04 15 2
5 2019-01-05 20 2
6 2019-01-06 18 2
7 2019-01-07 2 3
8 2019-01-08 4 3
9 2019-01-09 9 3
Category
列是根据 TotalOrder
值的范围计算的。
如果TotalOrder
的值小于10,则增加Category
的值。
您可以使用 LAG
和 SUM OVER()
:
-- Create sample data
CREATE TABLE #Tbl(
ID INT,
OrderDate DATE,
TotalOrder INT
);
INSERT INTO #Tbl VALUES
(1, '2019-01-01', 5), (2, '2019-01-02', 3), (3, '2019-01-03', 1),
(4, '2019-01-04', 15), (5, '2019-01-05', 20), (6, '2019-01-06', 18),
(7, '2019-01-07', 2), (8, '2019-01-08', 4), (9, '2019-01-09', 9);
-- Query
WITH Cte AS(
SELECT *,
LessThanTen = CASE WHEN TotalOrder < 10 THEN 1 ELSE 0 END
FROM #Tbl
),
CteLag AS (
SELECT *,
Prev = LAG(LessThanTen, 1, NULL) OVER(ORDER BY OrderDate, ID)
FROM Cte
)
SELECT
ID,
OrderDate,
TotalOrder,
Category = SUM(CASE WHEN Prev = LessThanTen THEN 0 ELSE 1 END) OVER(ORDER BY OrderDate, ID)
FROM CteLag
ORDER BY OrderDate, ID;
-- Cleanup
DROP TABLE #Tbl;
根据样本数据和预期结果,
我认为你的意思是每次当前行的 TotalOrder
列与前一行的 TotalOrder
列之间的差异为 10 或更高时,你想要向 category
列添加一个,当顺序行由 OrderDate
列决定。
因此,借助 Felix 回答中的样本数据,我认为您正在寻找这样的东西:
WITH CTE AS
(
SELECT Id,
OrderDate,
TotalOrder,
-- IIF is shorthand for case then else
IIF(
-- if the difference in TotalOrder between current row and previous row is more than 10.
ABS(TotalOrder - ISNULL(LAG(TotalOrder) OVER(ORDER BY OrderDate), TotalOrder - 11)) > 10
, 1
, 0
) As IsDiffMoreThanTen
FROM #Tbl
)
SELECT Id,
OrderDate,
TotalOrder,
-- sum the IsDiffMoreThanTen column over order by OrderDate.
SUM(IsDiffMoreThanTen) OVER(ORDER BY OrderDate) AS Category
FROM CTE
结果:
Id OrderDate TotalOrder Category
1 01.01.2019 5 1
2 02.01.2019 3 1
3 03.01.2019 1 1
4 04.01.2019 15 2
5 05.01.2019 20 2
6 06.01.2019 18 2
7 07.01.2019 2 3
8 08.01.2019 4 3
9 09.01.2019 9 3
我的问题很简单,但我找不到解决方案 - 可能使用 window 函数,我有以下示例数据:
ID OrderDate TotalOrder
--------------------------
1 2019-01-01 5
2 2019-01-02 3
3 2019-01-03 1
4 2019-01-04 15
5 2019-01-05 20
6 2019-01-06 18
7 2019-01-07 2
8 2019-01-08 4
9 2019-01-09 9
要求的结果是:
ID OrderDate TotalOrder Category
-------------------------------------
1 2019-01-01 5 1
2 2019-01-02 3 1
3 2019-01-03 1 1
4 2019-01-04 15 2
5 2019-01-05 20 2
6 2019-01-06 18 2
7 2019-01-07 2 3
8 2019-01-08 4 3
9 2019-01-09 9 3
Category
列是根据 TotalOrder
值的范围计算的。
如果TotalOrder
的值小于10,则增加Category
的值。
您可以使用 LAG
和 SUM OVER()
:
-- Create sample data
CREATE TABLE #Tbl(
ID INT,
OrderDate DATE,
TotalOrder INT
);
INSERT INTO #Tbl VALUES
(1, '2019-01-01', 5), (2, '2019-01-02', 3), (3, '2019-01-03', 1),
(4, '2019-01-04', 15), (5, '2019-01-05', 20), (6, '2019-01-06', 18),
(7, '2019-01-07', 2), (8, '2019-01-08', 4), (9, '2019-01-09', 9);
-- Query
WITH Cte AS(
SELECT *,
LessThanTen = CASE WHEN TotalOrder < 10 THEN 1 ELSE 0 END
FROM #Tbl
),
CteLag AS (
SELECT *,
Prev = LAG(LessThanTen, 1, NULL) OVER(ORDER BY OrderDate, ID)
FROM Cte
)
SELECT
ID,
OrderDate,
TotalOrder,
Category = SUM(CASE WHEN Prev = LessThanTen THEN 0 ELSE 1 END) OVER(ORDER BY OrderDate, ID)
FROM CteLag
ORDER BY OrderDate, ID;
-- Cleanup
DROP TABLE #Tbl;
根据样本数据和预期结果,
我认为你的意思是每次当前行的 TotalOrder
列与前一行的 TotalOrder
列之间的差异为 10 或更高时,你想要向 category
列添加一个,当顺序行由 OrderDate
列决定。
因此,借助 Felix 回答中的样本数据,我认为您正在寻找这样的东西:
WITH CTE AS
(
SELECT Id,
OrderDate,
TotalOrder,
-- IIF is shorthand for case then else
IIF(
-- if the difference in TotalOrder between current row and previous row is more than 10.
ABS(TotalOrder - ISNULL(LAG(TotalOrder) OVER(ORDER BY OrderDate), TotalOrder - 11)) > 10
, 1
, 0
) As IsDiffMoreThanTen
FROM #Tbl
)
SELECT Id,
OrderDate,
TotalOrder,
-- sum the IsDiffMoreThanTen column over order by OrderDate.
SUM(IsDiffMoreThanTen) OVER(ORDER BY OrderDate) AS Category
FROM CTE
结果:
Id OrderDate TotalOrder Category
1 01.01.2019 5 1
2 02.01.2019 3 1
3 03.01.2019 1 1
4 04.01.2019 15 2
5 05.01.2019 20 2
6 06.01.2019 18 2
7 07.01.2019 2 3
8 08.01.2019 4 3
9 09.01.2019 9 3