SQL 查询以填补跨时间缺失的空白并获取最后一个非空值

Posted

技术标签:

【中文标题】SQL 查询以填补跨时间缺失的空白并获取最后一个非空值【英文标题】:SQL Query to fill missing gaps across time and get last non-null value 【发布时间】:2014-05-29 11:22:07 【问题描述】:

我的数据库中有下表:

Month|Year | Value
   1 |2013 | 100
   4 |2013 | 101
   8 |2013 | 102
   2 |2014 | 103
   4 |2014 | 104 

如何从数据中填写“缺失”行,这样如果我从 2013 年 3 月到 2014 年 3 月查询,我会得到:

Month|Year | Value
   3 |2013 | 100
   4 |2013 | 101
   5 |2013 | 101
   6 |2013 | 101
   7 |2013 | 101
   8 |2013 | 102
   9 |2013 | 102
  10 |2013 | 102
  11 |2013 | 102
  12 |2013 | 102
   1 |2014 | 102
   2 |2014 | 103
   3 |2014 | 103

如您所见,我想重复前面的Value 来查找缺失的行。

【问题讨论】:

您这样做的原因是什么?到目前为止您做了什么尝试?如果你给你的问题更多的背景,并展示你的努力,你会得到一个更好的答案。 @Tanner 目的是比较一个月没有数据的数据,因为在我们的表中是这样减少表中数据的。 最简单的方法是创建一个查找表,其中包含要加入的所有月份和年份。如果该日期组合不存在,值将返回 null,此时您将计算要插入的值。 使用日历表,其中包含感兴趣期间每年每个月的每一天。 【参考方案1】:

我创建了这个解决方案的SQL Fiddle 供您使用。

基本上它会创建一个工作表@Months,然后交叉连接这将在您的数据集中的所有年份。这会生成所有年份的所有月份的完整列表。然后,我将示例中提供的测试数据(名为 TEST 的表 - 请参阅 SQL fiddle for schema)加入此列表,为我提供一个完整列表,其中包含包含它们的月份的值。下一个要克服的问题是如果本月没有任何值,则使用最后几个月的值。为此,我使用了一个相关的子查询,即仅在与具有值的行的最大排名匹配的地方将 tblValues 加入自身。这会给出一个完整的结果集!

如果您想按年\月过滤,您可以将其添加到 WHERE 子句中,就在最后的 Order By 之前。

享受吧!

测试架构

CREATE TABLE TEST( Month tinyint, Year int, Value int)

INSERT INTO TEST(Month, Year, Value)
VALUES
   (1,2013,100),
   (4,2013,101),
   (8,2013,102),
   (2,2014,103),
   (4,2014,104)

查询

DECLARE @Months Table(Month tinyint)
Insert into @Months(Month)Values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);


With tblValues as (
  select Rank() Over (ORDER BY y.Year, m.Month) as [Rank], 
          m.Month, 
          y.Year, 
          t.Value
  from @Months m
  CROSS JOIN ( Select Distinct Year from Test ) y
  LEFT JOIN Test t on t.Month = m.Month and t.Year = y.Year
  )
Select t.Month, t.Year, COALESCE(t.Value, t1.Value) as Value
from tblValues t
left join tblValues t1 on t1.Rank = (
            Select Max(tmax.Rank)
            From tblValues tmax 
            Where tmax.Rank < t.Rank AND tmax.Value is not null)

Order by t.Year, t.Month

【讨论】:

你给出的答案是正确的,但如果数据是 2012 年和 2014 年的,那么我只会得到 2012 年 1-12 年和 2014 年 1-12 年的数据 在这种情况下,您可能需要将“Select Distinct Year from Test”替换为另一个填写您感兴趣的年份的工作表。例如“从@Years 中选择年份”。这可以通过多种方式从您的数据中填充。通过一个循环。通过从 min(year) 开始的行号,甚至像我几个月以来那样手动操作。

以上是关于SQL 查询以填补跨时间缺失的空白并获取最后一个非空值的主要内容,如果未能解决你的问题,请参考以下文章

填补雪花中缺失的数据

使用 SQL 查找数据库记录中的空白(缺失记录)

复制记录以填补 Google BigQuery 中日期之间的空白

填补 MultiIndex Pandas Dataframe 中的日期空白

填补Mysql查询中时间序列空白的最佳方法

用电量查询填补时间空白