我有一项服务,客户可以打开一个“客户服务票”,这是收费的。每当他们这样做,他们可以打开多少“客户服务票”,他们想在未来30天内没有被收费;在此期间之后,如果他们再次打开一个票,他们将再次收费(如果发生这种情况,他们将有另一个30天的免费客户服务)。
在此基础上,我有一个名为customer_service_ticket的表,在其中存储每张票据,并将其日期存储在“date”列中。
什么查询获取所有可收费的票,也就是说,这些票打开30天的窗口(而不是其中的票)?
如果票上有日期
3/1月4日/1月8日/1月30日/1月4日/20日/20日/3月
查询应该只返回
1月3日至2月4日至3月20日
因为每个语句都应用于所有行,所以我找不到解决方案。我正在使用递归CTE。
2条答案
按热度按时间krcsximq1#
这种类型的问题需要递归CTE,因为选定的行依赖于先前选定的行。
下面演示了执行请求的操作的查询:
字符串
结果如下:
| 客户标识|机票ID|出票日期|
| --|--|--|
| 1 | 1 |2023-01-03 2023-01-03|
| 1 | 4 |2023-02-04 2023-02-04|
| 1 | 6 |2023-03- 20 2023-03-20 2023-03-20|
查询首先将示例数据建立为
tickets
(这将是一个用于生产的实际表)。支持天数在parms
中定义。这允许查询更DRY(Don 'tRepeatYourself)。递归CTE在
charged_tickets
中找到。初始化部分确定每个客户的第一张收费票据和下一次收费的日期。迭代部分对每个连续的收费票据执行相同的操作。charged_tickets
中的子查询是必要的,因为PostgreSQL在递归子查询中不直接支持DISTINCT ON
。nukf8bse2#
你说得太对了使用递归CTE对于这个特定的场景来说可能有点过于复杂。2相反,窗口函数和子查询的组合可以有效地实现所需的结果。3该方法包括识别每个30天窗口的开始日期,并仅选择那些票据。
假设您的表名为customer_service_ticket,并且包含ticket_id和date等列,则以下查询应提供所需的输出:
字符串
此查询返回客户服务票证的日期,这些票证标志着新的30天期间的开始,在此期间,客户可以打开其他“客户服务票证”而不收取费用。