【问题标题】:SQL - Calculate the difference in number of orders by monthSQL - 按月计算订单数量的差异
【发布时间】:2021-04-02 19:15:05
【问题描述】:

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

订单表是这样的

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

我的策略是自行加入this answer

这是我的尝试

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

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

【问题讨论】:

  • 你的任务很适合窗口函数和lag()
  • @Stu 假设(与我的任务相关)窗口函数不可用。这基本上意味着有一个不依赖于滞后的解决方案
  • 啊 - 好吧,我刚刚发布了一个使用 lag 的示例 - 抱歉,您没有提供不要使用的语法列表,哈哈 ;-)

标签: sql sql-server join left-join self-join


【解决方案1】:

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

LAG 提供对位于给定物理偏移量的行的访问 在当前行之前。

所以,这就是你需要的:

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窗口函数的解决方案:

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;

【讨论】:

  • 有一个假设(与我的任务相关)窗口函数不可用。这基本上意味着有一个不依赖于滞后的解决方案。此外,您的语句会导致解析错误 "SyntaxError: Parse error on line 4: ...MONTH(order_date))) OVER (ORDER BY (SELE"
  • @AbdelrahmanShoman 如果您直接在数据库上执行,此解决方案将有效,如果您在附加的网站上尝试,它将无效,因为它不支持窗口功能。我已经更新了我的答案并附上了 SQL Fiddle 链接。
  • Maeisc,我明白了,谢谢。但是,我假设我不能使用窗口函数(这与我的任务有关)。这就是为什么我假设解决方案将使用连接
  • @AbdelrahmanShoman 我已经为你写了一个声明,没有使用窗口函数。
【解决方案2】:

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

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

【讨论】:

  • 这会给我一个语法错误“SyntaxError: Parse error on line 1: ...lag(Total_orders,1) over(order by Month)”。你可以在这里试试:techonthenet.com/sql/select_try_sql.php
  • @AbdelrahmanShoman 如果您尝试我在答案中附加的 SQL Fiddle 链接,相同的查询将返回正确的结果。
  • @AbdelrahmanShoman 在那种情况下似乎不支持 SQLServer 语法 - 上面的 lag 语句很好,我刚刚在 SQLServer 中检查过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-24
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多