SQL 查询获取按月分组的最近 6 个月的数据?
SQL query for getting data for the last 6 months grouped by month?
我知道一个基本查询可以获取过去 6 个月的一些结果。让我们这样说:
SELECT *
FROM RANDOM_TABLE
WHERE Date_Column >= DATEADD(MONTH, -6, GETDATE())
但是如果我想获得按月分组的结果 - 每个月回顾过去 6 个月怎么办?
理想情况下,结果的前三行如下所示(ID 的数量是随机的):
Month_and_year
COUNT(ID)
January 2017
120
February 2017
160
March 2017
240
最后三行:
Month_and_year
COUNT(ID)
November 2021
80
December 2021
350
January 2021
260
希望这是可以理解的。
提前致谢!
编辑:
在几个小时内,我做了一些更正。最值得注意的是,我更正了自连接查询以反映我的意图,还添加了更多详细信息以更好地解释正在发生的事情。
据我所知,有两种方法(它们在底层可能是相同的)。
另外,请注意这些解决方案假设您已经有一个月份字段。如果您有日期或时间戳字段,则应采取额外的准备步骤。
[附录] 更准确地说,我想说理想的情况是有一个 date/timestamp 字段,即 truncated/flattened 到每月的第一天。
举个例子,
month
amount
2021-01-01
50
2021-02-01
20
2021-03-01
10
2021-04-01
100
2021-05-01
20
2021-06-01
40
2021-07-01
80
2021-08-01
50
第一种是使用“self-non-equi加入”
SELECT
a.month,
SUM(b.amount) AS amount_over_6_months
FROM table AS a
INNER JOIN table AS b ON a.month BETWEEN b.month AND DATEADD(MONTH, 5, b.month)
WHERE a.month >= DATEADD(MONTH, -5, GETDATE())
GROUP BY a.month
这里发生的是你加入了 table 本身。具体来说,对于 (a) 别名中的每一行,您将连接来自 (b) 别名的六行。对于每一行,您将加入月份相同的行,一直追溯到五个月之前。所以...
a.month
b.month
a.amount
b.amount
2021-01-01
2021-01-01
50
50
2021-02-01
2021-01-01
20
50
2021-02-01
2021-02-01
20
20
2021-03-01
2021-01-01
10
50
2021-03-01
2021-02-01
10
20
2021-03-01
2021-03-01
10
10
2021-04-01
2021-01-01
100
50
2021-04-01
2021-02-01
100
20
2021-04-01
2021-03-01
100
10
2021-04-01
2021-04-01
100
100
2021-05-01
2021-01-01
20
50
2021-05-01
2021-02-01
20
20
2021-05-01
2021-03-01
20
10
2021-05-01
2021-04-01
20
100
2021-05-01
2021-05-01
20
20
2021-06-01
2021-01-01
40
50
2021-06-01
2021-02-01
40
20
2021-06-01
2021-03-01
40
10
2021-06-01
2021-04-01
40
100
2021-06-01
2021-05-01
40
20
2021-06-01
2021-06-01
40
40
2021-07-01
2021-02-01
80
20
2021-07-01
2021-03-01
80
10
2021-07-01
2021-04-01
80
100
2021-07-01
2021-05-01
80
20
2021-07-01
2021-06-01
80
40
2021-07-01
2021-07-01
80
80
...
...
...
...
然后只需根据 (a) 别名中的月份进行分组,然后对来自 (b) 别名的金额求和即可。
这种方法的优点是它应该与供应商和代无关,保存 DATEADD()
函数。
第二种解决方案是使用 window 函数。我无法评论这是否适用于您的供应商和特定版本。
SELECT
month,
SUM(amount) OVER (ORDER BY month ROWS BETWEEN 5 PRECEDING AND CURRENT ROW)
FROM table
我知道一个基本查询可以获取过去 6 个月的一些结果。让我们这样说:
SELECT *
FROM RANDOM_TABLE
WHERE Date_Column >= DATEADD(MONTH, -6, GETDATE())
但是如果我想获得按月分组的结果 - 每个月回顾过去 6 个月怎么办? 理想情况下,结果的前三行如下所示(ID 的数量是随机的):
Month_and_year | COUNT(ID) |
---|---|
January 2017 | 120 |
February 2017 | 160 |
March 2017 | 240 |
最后三行:
Month_and_year | COUNT(ID) |
---|---|
November 2021 | 80 |
December 2021 | 350 |
January 2021 | 260 |
希望这是可以理解的。 提前致谢!
编辑: 在几个小时内,我做了一些更正。最值得注意的是,我更正了自连接查询以反映我的意图,还添加了更多详细信息以更好地解释正在发生的事情。
据我所知,有两种方法(它们在底层可能是相同的)。
另外,请注意这些解决方案假设您已经有一个月份字段。如果您有日期或时间戳字段,则应采取额外的准备步骤。
[附录] 更准确地说,我想说理想的情况是有一个 date/timestamp 字段,即 truncated/flattened 到每月的第一天。
举个例子,
month | amount |
---|---|
2021-01-01 | 50 |
2021-02-01 | 20 |
2021-03-01 | 10 |
2021-04-01 | 100 |
2021-05-01 | 20 |
2021-06-01 | 40 |
2021-07-01 | 80 |
2021-08-01 | 50 |
第一种是使用“self-non-equi加入”
SELECT
a.month,
SUM(b.amount) AS amount_over_6_months
FROM table AS a
INNER JOIN table AS b ON a.month BETWEEN b.month AND DATEADD(MONTH, 5, b.month)
WHERE a.month >= DATEADD(MONTH, -5, GETDATE())
GROUP BY a.month
这里发生的是你加入了 table 本身。具体来说,对于 (a) 别名中的每一行,您将连接来自 (b) 别名的六行。对于每一行,您将加入月份相同的行,一直追溯到五个月之前。所以...
a.month | b.month | a.amount | b.amount |
---|---|---|---|
2021-01-01 | 2021-01-01 | 50 | 50 |
2021-02-01 | 2021-01-01 | 20 | 50 |
2021-02-01 | 2021-02-01 | 20 | 20 |
2021-03-01 | 2021-01-01 | 10 | 50 |
2021-03-01 | 2021-02-01 | 10 | 20 |
2021-03-01 | 2021-03-01 | 10 | 10 |
2021-04-01 | 2021-01-01 | 100 | 50 |
2021-04-01 | 2021-02-01 | 100 | 20 |
2021-04-01 | 2021-03-01 | 100 | 10 |
2021-04-01 | 2021-04-01 | 100 | 100 |
2021-05-01 | 2021-01-01 | 20 | 50 |
2021-05-01 | 2021-02-01 | 20 | 20 |
2021-05-01 | 2021-03-01 | 20 | 10 |
2021-05-01 | 2021-04-01 | 20 | 100 |
2021-05-01 | 2021-05-01 | 20 | 20 |
2021-06-01 | 2021-01-01 | 40 | 50 |
2021-06-01 | 2021-02-01 | 40 | 20 |
2021-06-01 | 2021-03-01 | 40 | 10 |
2021-06-01 | 2021-04-01 | 40 | 100 |
2021-06-01 | 2021-05-01 | 40 | 20 |
2021-06-01 | 2021-06-01 | 40 | 40 |
2021-07-01 | 2021-02-01 | 80 | 20 |
2021-07-01 | 2021-03-01 | 80 | 10 |
2021-07-01 | 2021-04-01 | 80 | 100 |
2021-07-01 | 2021-05-01 | 80 | 20 |
2021-07-01 | 2021-06-01 | 80 | 40 |
2021-07-01 | 2021-07-01 | 80 | 80 |
... | ... | ... | ... |
然后只需根据 (a) 别名中的月份进行分组,然后对来自 (b) 别名的金额求和即可。
这种方法的优点是它应该与供应商和代无关,保存 DATEADD()
函数。
第二种解决方案是使用 window 函数。我无法评论这是否适用于您的供应商和特定版本。
SELECT
month,
SUM(amount) OVER (ORDER BY month ROWS BETWEEN 5 PRECEDING AND CURRENT ROW)
FROM table