【问题标题】:SQL - How to group/count items by age and status on every date of a year?SQL - 如何在一年中的每个日期按年龄和状态对项目进行分组/计数?
【发布时间】:2020-09-17 14:56:14
【问题描述】:

我正在尝试从支持票证的多年数据集(tickets 表)构建查询,每个票证的相关列为ticked_idstatuscreated_on 日期和closed_on 日期.还有一个通用的dates 表,我可以加入/查询日期列表。

我想为今年创建一个“燃尽”图表,显示在今年任何给定日期至少存在一年的未结门票数量。我已经能够创建使用sum(case... 语句按日期分组的表格 - 例如显示在给定的一周内创建了多少票 - 但我无法弄清楚如何每天或每周分组year 当天开放的票数,并且至少有一年的历史。

感谢任何帮助。

示例数据:

ticket_id | status | created_on | closed_on
--------------------------------------------
 1          open     1/5/2019     
 2          open     1/26/2019
 3          closed   1/28/2019    2/1/2020
 4          open     6/1/2019
 5          closed   6/5/2019     1/1/2020

我寻求的示例结果:

Date (2020)    |     Count of Year+ Aged Tickets
------------------------------------------------
1/1/2020             0
1/2/2020             0
1/3/2020             0
1/4/2020             0
1/5/2020             1
1/6/2020             1
... (skipping dates here but want all dates in results)...
1/25/2020            1
1/26/2020            2
1/27/2020            2
1/28/2020            3
1/29/2020            3
1/30/2020            3
1/31/2020            3
2/1/2020             2
... (skipping dates here but want all dates up to current date in results)...
  • ticket_id 1 已于 2020 年 1 月 5 日满一岁,仍在营业 (仍在计数中)
  • ticket_id 2 已于 2020 年 1 月 26 日满一岁,仍在营业(仍在计数中)
  • ticket_id 3 于 2020 年 1 月 28 日满一岁,仍然营业,增加计数,但于 2020 年 2 月 1 日关闭,减少计数
  • ticket_id 4 仅在 2020 年 6 月 1 日仍营业时才会增加计数,但在此之前关闭则不会增加计数
  • ticket_id 5 永远不会出现在计数中,因为它从未达到一岁并且已关闭

【问题讨论】:

  • 请用您正在运行的数据库标记您的问题:mysql、oracle、sql-server...?此外,示例数据、预期结果和您当前的查询都会有所帮助。
  • 感谢 - 添加了示例数据和预期结果。

标签: sql date join amazon-redshift recursive-query


【解决方案1】:

一种选择是构建一个顺序的日期列表,然后使用“左连接”和条件逻辑将该表引入,最后进行聚合。

这将给出您想要的 2020 年结果。

select d.dt, count(t.ticket_id) no_tickets
from (
    select date '2020-01-01' + I * interval '1 day' dt 
    from generate_series(0, 365) i 
) d
left join mytable t
    on t.created_on + interval '1 year' <= d.dt 
    and (
        t.closed_on is null 
        or t.closed_on > d.dt
    )
group by d.dt

如果您的 Redshift 版本不支持 generate_series(),您可以将其模拟为自定义数字表,或使用 row_number() 模拟大表(例如 mylargetable):

select d.dt, count(t.ticket_id) no_tickets
from (
    select date '2020-01-01' + row_number() over(order by 1) * interval '1 day' dt 
    from mylargetable 
) d
left join mytable t
    on t.created_on + interval '1 year' <= d.dt 
    and (
        t.closed_on is null 
        or t.closed_on > d.dt
    )
where d.dt < date '2021-01-01'
group by d.dt

【讨论】:

  • 谢谢!我得到了错误"Error running query: Specified types or functions (one per INFO message) not supported on Redshift tables."generate_series 子查询正在运行,我将继续进行故障排除。如果我修复它,我会报告,但如果您有其他想法,请告诉我。
  • 我做了更多研究,发现 generate_series 函数在 redshift 中不完全支持。我可以通过从可用的“日期”表中提取日期子集来修复查询,而不是使用 generate_series 来完成。
  • @jdrunbike:没有记录,但显然至少some versions of Redshift support it。但实际上,您可以在一张大桌子上使用 row_number() 来模拟这一点。我在答案中添加了一个示例。
【解决方案2】:

如果 ticket_id 是唯一的,那么您可以这样做以获得至少 1 年的所有票

select ticket_id, created_on , status where status = 'open' and created_on <= dateadd(year,-1,getdate())

如果你想计算每个月的票数,那么

select count(ticket_id), month(created_on) , status where status = 'open' and created_on <= dateadd(year,-1,getdate())
group by month(created_on)

【讨论】:

  • 感谢您的回复!这些选项中的任何一个都不会返回按月创建的现已超过一年的票数吗?这似乎是我得到的结果。我需要一些东西来返回 1 月 1 日有多少年的开放票,然后是 1 月 2 日有多少张,依此类推(有些票可能会每天关闭,减少计数,有些可能会达到一年或任何一天的年龄都更大,从而增加计数)。这有意义吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 2019-02-23
相关资源
最近更新 更多