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
不使用LAG
window函数的解决方案:
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
我正在处理此 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
不使用LAG
window函数的解决方案:
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