sqlite - 忽略 lag/lad 中的空值

Posted

技术标签:

【中文标题】sqlite - 忽略 lag/lad 中的空值【英文标题】:sqlite - ignore nulls in lag/lad 【发布时间】:2021-02-14 16:09:45 【问题描述】:

我使用 sqlite 并有两个表。第一个包含一系列无间隙的日期(下面的表 datelist),第二个包含日期和值(表:valuelist)。第二张表在日期系列中有空白。结果,我希望有一个无间隙的时间序列值。如果对于给定的一天 valuelist 中没有值,我假设那一天之前的最后一个值 NULL 是最好的近似值。

使用我的 SQL,我可以生成下表。 SQL 位于较大的表 (10^4) 和可能较大的间隙 (~100) 上,这是可以理解的,性能不佳。

lag(value, 100), ..., lag(value, 1) 的合并至少不优雅。 (不知道有没有用)

问题:有没有更高效(和优雅)的方式在 SQLite 中编写它?在其他 SQL 俚语中,窗口函数中有一个 IGNORE NULLS。 SQLites 似乎没有它们。 Window Functions 的 FILTER 部分也起作用 - lag 不是聚合函数。不能使用 max() 左右 - 值没有排序。

SELECT * FROM  
(
    SELECT d.dDate AS dDate, v.vDate
    , julianday(d.dDate) - julianday(v.vDate) AS diff
    , min(julianday(d.dDate) - julianday(v.vDate)) OVER (PARTITION BY d.dDate) AS min_diff
    , v.value
    FROM datelist AS d
    LEFT OUTER JOIN valuelist AS v 
    ON  d.dDate >= v.vDate
    AND julianday(d.dDate) - JULIANDAY(v.vDate) < 30    
    order by d.dDate DESC, v.vDate
) 
WHERE diff = min_diff
dDate vDate diff min_diff value comment
2021-02-10 2021-02-09 1.0 1.0 6 gap - value from 09-02
2021-02-09 2021-02-09 0.0 0.0 6
2021-02-08 2021-02-08 0.0 0.0 7
2021-02-07 2021-02-04 3.0 3.0 3 gap - value from 04-02
2021-02-06 2021-02-04 2.0 2.0 3 gap - value from 04-02
2021-02-05 2021-02-04 1.0 1.0 3 gap - value from 04-02
2021-02-04 2021-02-04 0.0 0.0 3
2021-02-03 2021-02-02 1.0 1.0 4 gap - value from 02-02
2021-02-02 2021-02-02 0.0 0.0 4
2021-02-01 2021-02-01 0.0 0.0 3
DROP TABLE IF EXISTS datelist;
CREATE TABLE datelist (dDate text);
INSERT INTO datelist values('2021-02-01');
INSERT INTO datelist values('2021-02-02');
INSERT INTO datelist values('2021-02-03');
INSERT INTO datelist values('2021-02-04');
INSERT INTO datelist values('2021-02-05');
INSERT INTO datelist values('2021-02-06');
INSERT INTO datelist values('2021-02-07');
INSERT INTO datelist values('2021-02-08');
INSERT INTO datelist values('2021-02-09');
INSERT INTO datelist values('2021-02-10');

DROP TABLE IF EXISTS valuelist;
CREATE TABLE valuelist(vDate text, value int );
INSERT INTO valuelist values('2021-02-01', 3);
INSERT INTO valuelist values('2021-02-02', 4);
INSERT INTO valuelist values('2021-02-04', 3);
INSERT INTO valuelist values('2021-02-08', 7);
INSERT INTO valuelist values('2021-02-09', 6);

【问题讨论】:

【参考方案1】:

一个简单的方法是使用lead() 来获取值表的范围。然后将结果连接在一起:

select d.*, v.value
from datelist d left join
     (select v.*, lead(vdate) over (order by vdate) as next_vdate
      from valuelist v
     ) v
     on d.dDate >= v.vDate and
        (d.dDate < v.next_vdate or v.next_vdate is null);

Here 是一个 dbfiddle。

【讨论】:

将其重写为我的原始问题,它完全符合我的要求 :-) 谢谢!有趣的事实:我之前使用相同的想法来找出间隙的长度。我很难复杂...最后很容易:-) - 确定序列中间隙的长度: SELECT lag(vdate) OVER (ORDER BY vdate) , vdate , julianday(vdate) - julianday(lag(vdate ) OVER (ORDER BY vdate)) AS gap_length FROM valuelist ORDER BY gap_length

以上是关于sqlite - 忽略 lag/lad 中的空值的主要内容,如果未能解决你的问题,请参考以下文章

如何忽略 PostgreSQL 窗口函数中的空值?或返回列中的下一个非空值

将列分组为一行,忽略 postgreSQL 中的空值

Linux/bash 解析文本输出,选择字段,仅忽略一个字段中的空值

如何定义一个维度,以便在显示所有值时不忽略 FK 中的空值?

MySQL 是不是忽略唯一约束的空值?

SQL 查询数据连接具有它忽略的空值