基于条件组的连续月份总和

时间:2020-01-09 23:09:23

标签: sql-server aggregate-functions window-functions gaps-and-islands ranking-functions

在缩小连续几个月出现的主要地区的销售方面,我遇到了麻烦。我知道我需要对Row_NumberDense_Rank使用某种形式的窗口函数,但是在获取最终输出时遇到了困难

这是我的源数据:

+--------+-----------+------------+
| Fruit  | SaleDate  | Top_Region |
+--------+-----------+------------+
| Apple  | 1/1/2017  |          1 |
| Apple  | 2/1/2017  |          1 |
| Apple  | 3/1/2017  |          1 |
| Apple  | 4/1/2017  |          0 |
| Apple  | 5/1/2017  |          0 |
| Apple  | 6/1/2017  |          0 |
| Apple  | 7/1/2017  |          1 |
| Apple  | 8/1/2017  |          1 |
| Apple  | 9/1/2017  |          1 |
| Apple  | 10/1/2017 |          1 |
| Apple  | 11/1/2017 |          0 |
| Apple  | 12/1/2017 |          0 |
| Banana | 1/1/2017  |          0 |
| Banana | 2/1/2017  |          0 |
| Banana | 3/1/2017  |          1 |
| Banana | 4/1/2017  |          1 |
| Banana | 5/1/2017  |          1 |
| Banana | 6/1/2017  |          1 |
| Banana | 7/1/2017  |          1 |
| Banana | 8/1/2017  |          1 |
| Banana | 9/1/2017  |          0 |
| Banana | 10/1/2017 |          1 |
| Banana | 11/1/2017 |          1 |
| Banana | 12/1/2017 |          0 |
+--------+-----------+------------+

这是预期的输出:

+--------+-----------+-----------+-------+
| Fruit  |   Start   |    End    | Total |
+--------+-----------+-----------+-------+
| Apple  | 1/1/2017  | 3/1/2017  |     3 |
| Apple  | 7/1/2017  | 10/1/2017 |     4 |
| Banana | 3/1/2017  | 8/1/2017  |     6 |
| Banana | 10/1/2017 | 11/1/2017 |     2 |
+--------+-----------+-----------+-------+

目标是连续一个月在顶级地区销售实例,而在一个月内消失。

到目前为止,我已经尝试了几种不同的组合,这是最接近的组合。

SELECT fruit,
        MIN(saledate) AS spanStart ,
        MAX(saledate) AS spanEnd,
        COUNT(*) AS spanLength
FROM    ( SELECT    s.* ,
                    ( ROW_NUMBER() OVER ( ORDER BY month )
                      - ROW_NUMBER() OVER ( PARTITION BY fruit, topregion ORDER BY month ) ) AS fruits
          FROM      #salesdata s
        ) s
GROUP BY fruit,fruits ,
        topregion
HAVING  topregion = 1
ORDER BY COUNT(*) DESC;

任何帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

这是一个典型的隔岛问题。一种策略是通过计算两个row_number()之间的差异来识别相邻行组的组。然后,我们可以过滤具有top_region = 1的组,并使用汇总来获取每个组的开始日期,结束日期和记录数。

您的查询确实很接近,但是第一个row_number()的{​​{1}}子句中缺少partition by fruit。而且我发现在另一列称为over()的列fruits上使用别名是容易出错的。

fruit

您可以单独运行内部查询以查看其产生的结果。

Demo on DB Fiddle

fruit  | start_date | end_date   | total
:----- | :--------- | :--------- | ----:
Apple  | 2017-01-01 | 2017-01-03 |     3
Apple  | 2017-01-07 | 2017-01-10 |     4
Banana | 2017-01-03 | 2017-01-08 |     6
Banana | 2017-01-10 | 2017-01-11 |     2