SQL - 重复最后一个已知值,直到昨天

Posted

技术标签:

【中文标题】SQL - 重复最后一个已知值,直到昨天【英文标题】:SQL - Repeat the last known value until yesterday 【发布时间】:2019-02-01 16:37:17 【问题描述】:

我有一个包含日期、ID 和值的表格。对于某些 ID,我没有到昨天的值。我需要重复每个 ID 的最后一个已知值,直到昨天它为 NULL。 我已经使用 CTE 来填充 2 个非 NULL 值之间的 NULL 值,但直到昨天才能填充。 数据如下所示:

+-----------+-----+-------+
|   Date    | ID  | Value |
+-----------+-----+-------+
| 1/25/2019 | 111 |    50 |
| 1/26/2019 | 111 |   100 |
| 1/27/2019 | 111 |   150 |
| 1/25/2019 | 222 |   500 |
| 1/26/2019 | 222 |  1000 |
| 1/27/2019 | 222 |  1500 |
+-----------+-----+-------+

我尝试了以下代码,但没有成功:

WITH CAwithnext AS (
  SELECT
    *,
    LEAD("date") OVER (PARTITION BY "id" ORDER BY "date") AS "NextValue"
  FROM "transform_data_1"
  )
SELECT
    c."Date",
    ig."id",
    ig."value"
FROM "calendar_from_2015_to_2025" AS c
JOIN "CAwithnext" AS ig
    ON c."Date" BETWEEN ig."date" AND ISNULL(DATEADD(day,-1,ig."NextValue"),ig."date")
;

这是预期的结果:

+-----------+-----+-------+
|   Date    | ID  | Value |
+-----------+-----+-------+
| 1/25/2019 | 111 |    50 |
| 1/26/2019 | 111 |   100 |
| 1/27/2019 | 111 |   150 |
| 1/28/2019 | 111 |   150 |
| 1/29/2019 | 111 |   150 |
| 1/30/2019 | 111 |   150 |
| 1/31/2019 | 111 |   150 |
| 1/25/2019 | 222 |   500 |
| 1/26/2019 | 222 |  1000 |
| 1/27/2019 | 222 |  1500 |
| 1/28/2019 | 222 |  1500 |
| 1/29/2019 | 222 |  1500 |
| 1/30/2019 | 222 |  1500 |
| 1/31/2019 | 222 |  1500 |
+-----------+-----+-------+

感谢您的帮助。

【问题讨论】:

能否添加您目前尝试过的代码? WITH CAwithnext AS ( SELECT *, LEAD("date") OVER (PARTITION BY "id" ORDER BY "date") AS "NextValue" FROM "transform_data_1" ) SELECT c."Date", ig."id", ig."value" FROM "calendar_from_2015_to_2025" AS c JOIN "CAwithnext" AS ig ON c."Date" BETWEEN ig."date" AND ISNULL(DATEADD(day,-1,ig."NextValue"),ig."date") ; 请使用此查询编辑您的问题 @APH,这是我使用的代码。但这仅适用于填充两个日期之间的缺失值。有边界时它不起作用。 @JonScott 刚刚做了。 【参考方案1】:

在提供的查询中,当日期是 id 的最后一个可用日期时,lead(“NextValue”)返回的下一个日期将是 NULL。当“NextValue”为NULL 时,要一直填写到昨天,您需要更改您的ISNULL,以便将NULL 替换为昨天的日期。

您当前拥有它的方式,当“NextValue”为空时,它会返回原始日期,这意味着对于任何id 的系列中的最后一个值,它只会加入您的日历表以获取确切的日期ig.date 原始条目的值。

例如,对于ID = 111,最后日期是 19/1/27,因此该行的“NextValue”将为NULL。如果您直接从 CTE 中进行选择,您应该会看到如下内容:

ID    Date    NextValue
111   1/26/18 1/27/19
111   1/27/19 NULL

当您加入您的日历时,您的ISNULL 有效地将您的加入条件转换为on c.Date between 1/27/19 and isnull(NULL, 1/27/19)on c.Date between 1/27/19 and 1/27/19,这就是为什么您只能为最后一个条目返回一行。

要解决问题,请将查询的最后一行从:

ISNULL(DATEADD(day,-1,ig."NextValue"),ig."date")

ISNULL(DATEADD(day,-1,ig."NextValue"),DATEADD(day,-1,GetDate()))

DATEADD(day,-1,ISNULL(ig."NextValue", GetDate()))

(基本上,将ig.date 替换为返回您希望它填充的日期的函数;即昨天)。

【讨论】:

谢谢@APH 由于我对 CTE 还很陌生,能否请您插入修改内容?我理解您的评论,但不知道如何解决。 您的 CTE 对我来说看起来不错 - 实际上只是需要更新日历表的联接。我会在答案中添加一些代码。

以上是关于SQL - 重复最后一个已知值,直到昨天的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 中获取上个月的昨天日期?有人可以帮我解决这个问题吗?

关于Inception默认配置的一个坑

SQL 查询今天、昨天、7天内、30天的数据

python 删除Slack中直到昨天上传的所有图像

python 删除Slack中直到昨天上传的所有图像

Android Room 获得昨天的最后记录