SQL递归添加日期,直到数据集每天有一条记录

Posted

技术标签:

【中文标题】SQL递归添加日期,直到数据集每天有一条记录【英文标题】:SQL Recursively add day to date until dataset has one record per day 【发布时间】:2014-12-04 06:14:40 【问题描述】:

我有一个包含lead_id、lead_status、effective_datetime 的数据集。状态可以在一天内更改几次。如果一天中有多个状态条目,我需要 DATE_ADD 1 天到第二个条目,2 天到第三个条目,等等,直到我有一个lead_id、lead_status、effective_day 记录。这是我目前所拥有的:

首先我创建一个行号:

CREATE TABLE lead_rows AS
SELECT
    lead_id,
    effective_datetime,
    lead_status,
    (
        CASE lead_id
        WHEN @curLead 
        THEN @curRow := @curRow + 1 
        ELSE @curRow := 1 AND @curLead := lead_id END
    ) + 1 AS row_number
FROM lead_history, (SELECT @curRow := 0, @curLead := '') r
ORDER BY lead_id, effective_datetime;

然后我将当前行与上一行进行比较,以确定是否需要将当前行日期提前一天:

SELECT
    lead_id,
    lead_status,
    effective_datetime,
    CASE 
        WHEN DATE(a.effective_datetime) = (
            SELECT DATE(effective_datetime) 
            FROM lead_rows 
            WHERE row_number = (a.row_number - 1) AND lead_id = a.lead_id) 
        THEN DATE_ADD(DATE(a.effective_datetime), INTERVAL 1 DAY) 
        ELSE DATE(a.effective_datetime) 
    END as new_date 
FROM lead_rows a;

这很好用,除非我在相邻的日子有两个状态条目。因为这不是递归的,所以它不会继续将后续状态条目向前推进一天。所以我可以开始:

lead_id    | lead_status    | effective_datetime
---------------------------------------------------
lead_1     | Known          | 2014-01-01 01:00:00
lead_1     | In Contact     | 2014-01-01 14:00:00
lead_1     | Unqualified    | 2014-01-02 12:00:00

但以:

结尾
lead_id    | lead_status    | effective_datetime    | new_date
----------------------------------------------------------------
lead_1     | Known          | 2014-01-01 01:00:00   | 2014-01-01
lead_1     | In Contact     | 2014-01-01 14:00:00   | 2014-01-02
lead_1     | Unqualified    | 2014-01-02 12:00:00   | 2014-01-02

应该是什么时候:

lead_id    | lead_status    | effective_datetime    | new_date
----------------------------------------------------------------
lead_1     | Known          | 2014-01-01 01:00:00   | 2014-01-01
lead_1     | In Contact     | 2014-01-01 14:00:00   | 2014-01-02
lead_1     | Unqualified    | 2014-01-02 12:00:00   | 2014-01-03

最后一个状态条目需要提前一天才能考虑到被推送的第二个条目,但我不知道递归地这样做。我已经研究过通过 Cursor 运行它,但这似乎有点矫枉过正,但也许没有其他办法......

有人对如何做到这一点有建议吗?我在 mysql 中运行它并能够设置过程,但如果有人有一个在 MySQL 中不起作用的选项,那么我可以将它转换为 RedShift。提前致谢。

【问题讨论】:

一个想法是一个包含所有相关日期的日历(这是一个令人沮丧的小表) 我最终会将其加入日历,因为我需要显示任何一天的状态,因为潜在客户可以在一个状态下多天。我认为首先扁平化这些历史数据会更容易(它有大约 9,000 条记录) 【参考方案1】:

问题在于 SQL 如何执行您的 +1 操作。 SQL 不必在显示给您的订单条目中进行检查..

我想一种更简单的方法是在添加条目时进行检查(假设这种日期冲突很少见)并在新条目插入表时使用trigger 来修改它。

编辑: Update int column in table with unique incrementing values 似乎是一个类似的问题,基本上你设置一个计数器 i 并将具有相同 id 相同日期的表从 0 开始增加 i。解决方案中的示例使用 i 中的日期。

【讨论】:

我同意这会更容易。不幸的是,我不拥有这些数据。我只得到系统的转储,然后我需要对其进行转换以进行报告。 如果时间紧迫,我会创建另一个表并使用触发器逐行传输(因为您只有 9000 个条目)。查看我的编辑以了解可能的替代方案 我最终写入另一个表以使用触发器调整日期以展平历史记录。如果有更多时间,我可以在您的编辑中调整解决方案以满足我的需求。谢谢!

以上是关于SQL递归添加日期,直到数据集每天有一条记录的主要内容,如果未能解决你的问题,请参考以下文章

sql用啥方法可以实现递归函数?

SQLAlchemy 递归查询结果集排序

如何取SQL结果集的第一条记录

SQL:我如何找到存在于 30 分钟日期时间范围内的“Created_at”列的数据集记录?

大数据集上的扁平化+分区与嵌套记录

proc sql加入SAS中最接近日期