【问题标题】:Histogram of orders by range of dates按日期范围排列的订单直方图
【发布时间】:2022-01-19 12:20:29
【问题描述】:

我正在尝试根据日期间隔和订单总数创建直方图,但我很难通过 SQL 对其进行分类。

下面是一个简化的表格

customer_id Date count_orders
1 01-01-2020 5
1 01-13-2020 26
1 02-06-2020 11
2 01-17-2020 9
3 02-04-2020 13
3 03-29-2020 24
4 04-05-2020 1
5 02-23-2020 10
6 03-15-2020 7
6 04-18-2020 32
... ... ...

我想把它分成 20 天的间隔,但我唯一能想到的就是做一个

SUM(CASE WHEN Date BETWEEN <interval1_startdate> AND <interval1_enddate> ...)

每个间隔的方法如果用于实际数据(包含数百万行)是相当累人的。所以我需要帮助自动化分箱部分。

期望的输出要么是

1)

interval total_count
01-01-2020 - 01-20-2020 31
01-21-2020 - 02-10-2020 24
02-10-2020 - 03-01-2020 10
... ...

或 2)

start end total_count
01-01-2020 01-20-2020 31
01-21-2020 02-10-2020 24
02-10-2020 03-01-2020 10
... ... ...

你有什么想法吗?

【问题讨论】:

  • 那么,对于您的样本数据,您所追求的结果是什么?
  • “group by”子句有什么问题?类似于 (PostgreSQL) GROUP BY round(extract('epoch' from Date) / 1.728.000)?您使用的是哪个 DBMS?
  • “你使用的是哪个 DBMS?” 他们的 OP 已经明确标记了 [sql-server] @aKiRa ...
  • 请注意,结果中的第一个间隔包含 20 天(如果包括两个边界)和第二个 - 21 天。第一个似乎缺少总和中的 2 01-17-2020 9 行。

标签: sql sql-server presto


【解决方案1】:

您可以按(当前日期 - 最短日期)/20 分组。对于这样的事情:

WITH dataset (customer_id, Date, count_orders) AS (
    VALUES (1, date_parse('01-01-2020', '%m-%d-%Y'), 5),
        (1, date_parse('01-13-2020', '%m-%d-%Y'), 26),
        (1, date_parse('02-06-2020', '%m-%d-%Y'), 11),
        (2, date_parse('01-17-2020', '%m-%d-%Y'), 9),
        (3, date_parse('02-04-2020', '%m-%d-%Y'), 13),
        (3, date_parse('03-29-2020', '%m-%d-%Y'), 24),
        (4, date_parse('04-05-2020', '%m-%d-%Y'), 1),
        (5, date_parse('02-23-2020', '%m-%d-%Y'), 10),
        (6, date_parse('03-15-2020', '%m-%d-%Y'), 7),
        (6, date_parse('04-18-2020', '%m-%d-%Y'), 32)
)

SELECT date_add('day', 20 * grp, min(min_date)) interval_end,
    date_add('day', 20 * (grp + 1) - 1, min(min_date)) interval_end,
    sum(count_orders) total_count
FROM (
        SELECT *,
            date_diff('day', min(date) over (), date) / 20 as grp,
            min(date) over () min_date
        FROM dataset
    )
group by grp
order by 1

输出:

interval_end interval_end total_count
2020-01-01 00:00:00.000 2020-01-20 00:00:00.000 40
2020-01-21 00:00:00.000 2020-02-09 00:00:00.000 24
2020-02-10 00:00:00.000 2020-02-29 00:00:00.000 10
2020-03-01 00:00:00.000 2020-03-20 00:00:00.000 7
2020-03-21 00:00:00.000 2020-04-09 00:00:00.000 25
2020-04-10 00:00:00.000 2020-04-29 00:00:00.000 32

【讨论】:

    【解决方案2】:

    您可以使用 CTE 获取间隔,然后使用 cross apply 获取总数。

    Drop table Tbl
    Create Table Tbl (customer_id Int, [date] Date, count_orders Int)
    
    Insert Into Tbl (customer_id, [date], count_orders)
    Values (1,'2020-01-01', 5),
           (1,'2020-01-13',26),
           (1,'2020-02-06',11),
           (2,'2020-01-17',9),
           (3,'2020-02-04',13),
           (3,'2020-03-29',24),
           (4,'2020-04-05',1),
           (5,'2020-02-23',10),
           (6,'2020-03-15',7),
           (6,'2020-04-18',32)
    
    
    ;With A As (
    Select Min([date]) As start, DateAdd(dd,19,Min([date])) As [end], Max([date]) As [max]
    From Tbl
    Union All
    Select DateAdd(dd,1,[end]) As start, DateAdd(dd,20,[end]) As [end], [max]
    From A
    Where [end]<[max])
    Select A.[start], A.[end], T.total_count
    From A Cross Apply (Select SUM(count_orders) As total_count 
                        From Tbl Where [date] between A.[start] And A.[end]) As T
    

    结果:

    start      end        total_count
    ---------- ---------- -----------
    2020-01-01 2020-01-20 40
    2020-01-21 2020-02-09 24
    2020-02-10 2020-02-29 10
    2020-03-01 2020-03-20 7
    2020-03-21 2020-04-09 25
    2020-04-10 2020-04-29 32
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 2019-08-26
      相关资源
      最近更新 更多