SQL - 按月计算订单数量的差异

SQL - Calculate the difference in number of orders by month

我正在处理此 site 提供的订单 table,它有自己的编辑器,您可以在其中测试您的 SQL 语句。

订单 table 看起来像这样

order_id customer_id order_date
1 7000 2016/04/18
2 5000 2016/04/18
3 8000 2016/04/19
4 4000 2016/04/20
5 NULL 2016/05/01

我想获取后续月份的订单数量差异。

具体来说,每个月的订单数是这样的

SQL声明

SELECT 
    MONTH(order_date) AS Month,
    COUNT(MONTH(order_date)) AS Total_Orders
FROM
    orders
GROUP BY
    MONTH(order_date)

结果:

Month Total_Orders
4 4
5 1

现在我的目标是在接下来的几个月中获得差异

Month Total_Orders Total_Orders_Diff
4 4 4 - Null = Null
5 1 1 - 4 = -3

我的策略是在

之后自行加入

这是我的尝试

SELECT 
    MONTH(a.order_date),
    COUNT(MONTH(a.order_date)),
    COUNT(MONTH(b.order_date)) - COUNT(MONTH(a.order_date)) AS prev,
    MONTH(b.order_date)
FROM 
    orders a
LEFT JOIN 
    orders b ON MONTH(a.order_date) = MONTH(b.order_date) - 1
GROUP BY
    MONTH(a.order_date)

但是,结果只是零(如下所示),这表明我只是从相同的值中减去而不是从上个月中减去(或从空值中减去)

MONTH(a.order_date) COUNT(MONTH(a.order_date)) prev MONTH(b.order_date)
4 4 0 NULL
5 1 0 NULL

你对我做错了什么有什么建议吗?

您必须在 SELECT 语句中使用 LAG window 函数。

LAG provides access to a row at a given physical offset that comes before the current row.

所以,这就是您需要的:

SELECT 
    MONTH(order_date)           as Month,
    COUNT(MONTH(order_date))    as Total_Orders,
    COUNT(MONTH(order_date)) - (LAG (COUNT(MONTH(order_date))) OVER (ORDER BY (SELECT NULL))) AS Total_Orders_Diff
FROM orders
GROUP BY MONTH(order_date);

此处以 SQL Fiddle 为例:http://sqlfiddle.com/#!18/5ed75/1

不使用LAGwindow函数的解决方案:

WITH InitCTE AS
(
    SELECT MONTH(order_date) AS Month,
           COUNT(MONTH(order_date)) AS Total_Orders
    FROM orders
    GROUP BY MONTH(order_date)
)
SELECT InitCTE.Month, InitCTE.Total_Orders, R.Total_Orders_Diff
FROM InitCTE
      OUTER APPLY (SELECT TOP 1 InitCTE.Total_Orders - CompareCTE.Total_Orders AS Total_Orders_Diff
                   FROM InitCTE AS CompareCTE
                   WHERE CompareCTE.Month < InitCTE.Month) R;

像下面这样的内容应该可以满足您的需求 - 免责声明,未经测试!

select *, Total_Orders - lag(Total_orders,1) over(order by Month) as Total_Orders_Diff
from (
 select Month(order_date) as Month, Count(*) as Total_Orders
 From orders
 Group by Month(order_date)
)o