【问题标题】:MS SQL - Grouping orders by month and showing the total yearly amount of orders for that yearMS SQL - 按月对订单进行分组并显示该年的年度订单总额
【发布时间】:2020-12-22 02:55:57
【问题描述】:

我需要创建一个查询来连接两个表中的数据:

  • [订单]
  • [人物]

并给出以下输出:

  • 销售人员 ID
  • 全名
  • 订单月份
  • 月订单量
  • 年订单量

这里的诀窍在于每年的订单量。虽然每月的订单量应按月份细分,但每个给定月份和销售人员的年度数量应相同。

我首先想到的是使用OVER (PARTITION BY <column x> ORDER BY <column y>)

所以,我想出了这个查询:

SELECT
    ORD.SalespersonPersonID,
    PEO.FullName,
    [Order Month] = MONTH(ORD.OrderDate),
    [Monthly Amount of Orders] = COUNT(ORD.OrderID),
    [Yearly Amount of Orders] = COUNT(ORD.OrderID) OVER (PARTITION BY ORD.SalespersonPersonID ORDER BY MONTH(ORD.OrderDate))
FROM [Sales].[Orders] ORD LEFT JOIN [Application].[People] PEO
ON ORD.SalespersonPersonID = PEO.PersonID
WHERE YEAR(ORD.OrderDate) = '2016'
GROUP BY ORD.SalespersonPersonID, PEO.FullName, MONTH(ORD.OrderDate), ORD.OrderID
ORDER BY PEO.FullName

问题是因为我必须在GROUP BY 中提及ORD.OrderID,它打破了每月聚合。

我采用了不同的方法并解决了这个问题(使用 CTE):

WITH table1 AS
(
SELECT 
    SalespersonPersonID,
    [Yearly Amount of Orders] = COUNT(OrderID)
FROM [Sales].[Orders]
WHERE YEAR(OrderDate) = '2016'
GROUP BY SalespersonPersonID
)
SELECT
    ORD.SalespersonPersonID,
    PEO.FullName,
    [Order Month] = MONTH(ORD.OrderDate),
    [Monthly Amount of Orders] = COUNT(ORD.OrderID),
    T1.[Yearly Amount of Orders]
FROM [Sales].[Orders] ORD
LEFT JOIN [Application].[People] PEO
ON ORD.SalespersonPersonID = PEO.PersonID
LEFT JOIN table1 AS T1
ON ORD.SalespersonPersonID = T1.SalespersonPersonID
WHERE YEAR(ORD.OrderDate) = '2016'
GROUP BY ORD.SalespersonPersonID, PEO.FullName, MONTH(ORD.OrderDate), T1.[Yearly Amount of Orders]
ORDER BY PEO.FullName

我仍然想知道如何使用OVER (PARTITION BY <column x> ORDER BY <column y>) 运行它。感觉这是解决这个问题的更优雅的方法。

谢谢,

迈克尔

【问题讨论】:

    标签: sql group-by count sum window-functions


    【解决方案1】:

    不需要 cte 或类似的东西。从您原来的 group by 查询开始,您会这样做:

    SUM(COUNT(ORD.OrderID)) OVER (PARTITION BY ORD.SalespersonPersonID 
        as [Yearly Amount of Orders]
    

    从概念上讲,窗口函数在执行聚合后 对结果集进行操作。然后,您可以访问每行的每月计数,并为销售人员总结全年。

    注意事项:

    • 您希望同一个人的所有行都具有相同的值,因此不要在 over() 子句中使用 order by 子句

    • 我怀疑OrderID 永远不会是null;如果是这样,则使用COUNT(*) 而不是COUNT(ORD.OrderID)。它更有效,因为数据库不需要检查nullity

    【讨论】:

    • 上帝在小细节中......每年金额中的加和超过计数解决了这个问题。感谢您的详细解释。
    【解决方案2】:

    我想你想要:

    SELECT
        ORD.SalespersonPersonID,
        PEO.FullName,
        [Order Month] = MONTH(ORD.OrderDate),
        [Monthly Amount of Orders] = COUNT(ORD.OrderID),
        [Yearly Amount of Orders] = SUM(COUNT(ORD.OrderID)) OVER (PARTITION BY ORD.SalespersonPersonID)
    FROM [Sales].[Orders] ORD LEFT JOIN
         [Application].[People] PEO
         ON ORD.SalespersonPersonID = PEO.PersonID
    WHERE YEAR(ORD.OrderDate) = '2016'
    GROUP BY ORD.SalespersonPersonID, PEO.FullName, MONTH(ORD.OrderDate)
    ORDER BY PEO.FullName;
    

    唯一的变化是每年的订单量。

    【讨论】:

    • 谢谢伙计,这正是我想要的。您应该从 GROUP BY 行提交 ORD.OrderID。
    • @Michael.s 。 . .是的,那不应该在那里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多