【问题标题】:Category column calculation with Window function in T-SQL在 T-SQL 中使用 Window 函数计算类别列
【发布时间】:2019-10-24 14:57:36
【问题描述】:

我的问题很简单,但我找不到解决方案 - 可能是窗口函数,我有以下示例数据:

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的值会增加。

【问题讨论】:

  • Totalordervalue 15 的类别值 2 是如何得到的,请详细解释一下
  • 如果您可以更清楚地了解类别计算并计算出针对它的范围,那么为您提供帮助会更容易
  • 类别从 1 开始,随着 TotalOrder 范围的变化而增加

标签: sql sql-server tsql window-functions


【解决方案1】:

您可以使用LAGSUM 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;

ONLINE DEMO

【讨论】:

    【解决方案2】:

    根据样本数据和预期结果,
    我认为您的意思是,当行的顺序由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
    

    【讨论】:

      猜你喜欢
      • 2021-08-29
      • 1970-01-01
      • 1970-01-01
      • 2020-10-01
      • 2020-06-23
      • 1970-01-01
      • 2019-05-21
      • 2013-04-11
      • 1970-01-01
      相关资源
      最近更新 更多