如何用列中的NULL值交换最后的非NULL值?

时间:2019-02-27 19:32:57

标签: sql postgresql sqlite

我正在实现一个不支持SQLite和PostgreSQL的查询。我的数据库有2个表,我想按日期排序,对传感器的值进行插值。我的桌子如下:

Valor_Sensor_Pressão:

ID_Sensor_Pressão |    Data_Medição    | Valor_Medido
1                  2016-01-01 10:20:05   13
1                  2016-01-01 10:20:06   11
1                  2016-01-01 10:20:12   20
1                  2016-01-01 10:20:13   0
1                  2016-01-01 10:21:05   100

Valor_Sensor_Temperatura:

ID_Sensor_Temperatura |    Data_Medição    | Valor_Medido
1                      2016-01-01 10:20:05   1
1                      2016-01-01 10:20:08   3
1                      2016-01-01 10:20:12   20
1                      2016-01-01 10:21:05   1
1                      2016-01-01 10:21:13   31

我使用以下SQL来按日期汇总和插值数据:

WITH Resultado (ValorPressão, ValorTemperatura, DataMedida) AS (
    SELECT
        p.Valor_Medido AS pValue,
        t.Valor_Medido AS tValue,
        COALESCE(p.Data_Medição, t.Data_Medição) AS DataMedida
    FROM Valor_Sensor_Pressão AS p
        LEFT JOIN Valor_Sensor_Temperatura AS t USING (Data_Medição)
    WHERE p.ID_Sensor_Pressão = 1
    UNION ALL
    SELECT
        p.Valor_Medido AS pValue,
        t.Valor_Medido AS tValue,
        COALESCE(p.Data_Medição, t.Data_Medição) AS DataMedida
    FROM Valor_Sensor_Temperatura AS t
        LEFT JOIN Valor_Sensor_Pressão AS p USING (Data_Medição)
    WHERE
        p.Data_Medição IS NULL
        AND t.ID_Sensor_Temperatura = 1
    ORDER BY COALESCE(p.Data_Medição, t.Data_Medição)
)

SELECT DataMedida, ValorPressão, ValorTemperatura FROM Resultado

结果如下:

"2016-01-01 10:20:05"   "13"    "1"
"2016-01-01 10:20:06"   "11"    NULL
"2016-01-01 10:20:08"   NULL    "3"
"2016-01-01 10:20:12"   "20"    "20"
"2016-01-01 10:20:13"   "0"     NULL
"2016-01-01 10:21:05"   "100"   "1"
"2016-01-01 10:21:13"   NULL    "31"

我已阅读以下page,并针对将在SQLite和PostgreSQL中使用的查询调整了解决方案:

WITH Resultado (ValorPressão, ValorTemperatura, DataMedida) AS (
    SELECT
        p.Valor_Medido AS pValue,
        t.Valor_Medido AS tValue,
        COALESCE(p.Data_Medição, t.Data_Medição) AS DataMedida
    FROM Valor_Sensor_Pressão AS p
        left join Valor_Sensor_Temperatura t USING (Data_Medição)
    WHERE p.ID_Sensor_Pressão = 1
    UNION ALL
    SELECT
        p.Valor_Medido AS pValue,
        t.Valor_Medido AS tValue,
        COALESCE(p.Data_Medição, t.Data_Medição) AS DataMedida
    FROM Valor_Sensor_Temperatura AS t
        LEFT JOIN Valor_Sensor_Pressão AS p USING (Data_Medição)
    WHERE
        p.Data_Medição IS NULL
        AND t.ID_Sensor_Temperatura = 1
    ORDER BY COALESCE(p.Data_Medição, t.Data_Medição)
)

SELECT
    DataMedida,
    COALESCE(last_value(ValorPressão) OVER (order by DataMedida), 0) AS ValorPressão,
    COALESCE(last_value(ValorTemperatura) over (order by DataMedida), 0) AS ValorTemperatura
FROM Resultado

我无法弄清楚什么是错误的,因为LAST_VALUE并没有给我前一个行值,所以COALESCE将0代替了前一个值,并且我找不到SQLite的IGNORE NULLS的替代品。

哪些修改将返回列的先前值而不是NULL?给我这样的东西:

"2016-01-01 10:20:05"   "13"    "1"
"2016-01-01 10:20:06"   "11"    "1"
"2016-01-01 10:20:08"   "11"    "3"
"2016-01-01 10:20:12"   "20"    "20"
"2016-01-01 10:20:13"   "0"     "20"
"2016-01-01 10:21:05"   "100"   "1"
"2016-01-01 10:21:13"   "100    "31"

编辑:将从其他表中获取的ID,因此我将WHERE选择为“ 1”进行测试。

2 个答案:

答案 0 :(得分:0)

您可以通过以下方式更轻松地实现当前查询:

select id, data, Valor_Medido, valor_temperatura
from (select ID_Sensor_Pressã as id, Data_Medição as data, Valor_Medido, null as valor_temperatura
      from valor_Sensor_Pressão
      union all
      select ID_Sensor_Temperatura, Data_Medição, null, Valor_Medido
      from Valor_Sensor_Temperatura
     ) v
group by id, data;

然后,您想要做的事情是在Postgres中使用窗口函数更轻松地完成。但是对于一般解决方案,您可以使用子查询:

with v as (
      select id, data, max(Valor_Medido) as Valor_Medido, max(valor_temperatura) as valor_temperatura
      from (select ID_Sensor_Pressã as id, Data_Medição as data, Valor_Medido, null as valor_temperatura
            from valor_Sensor_Pressão
            union all
            select ID_Sensor_Temperatura, Data_Medição, null, Valor_Medido
            from Valor_Sensor_Temperatura
           ) v
      group by id, data
     )
select v.*,
       coalesce(Valor_Medido,
                (select v2.Valor_Medido
                 from v v2
                 where v2.id = v.id and v2.data < v.data
                 order by v2.data desc
                 limit 1
                )
               ) as valor_medido,
       coalesce(valor_temperatura,
                (select v2.valor_temperatura
                 from v v2
                 where v2.id = v.id and v2.data < v.data
                 order by v2.data desc
                 limit 1
                )
               ) as valor_temperatura,
from v;

答案 1 :(得分:0)

我已经解决了问题,我在LAG和LAST_VALUE上犯了一个错误。解决方案是将两者合并到最后一个COALESCE中,并添加FIRST_VALUE。

我在“Valor_Sensor_Pressão”中添加了新行,以检查第一行是否为NULL:

"1" "2016-01-01 10:20:00"   "5.5"

所以我的最后一个查询是:

WITH Resultado (ValorPressão, ValorTemperatura, DataMedida) AS (
    SELECT
        p.Valor_Medido AS pValue,
        t.Valor_Medido AS tValue,
        COALESCE(p.Data_Medição, t.Data_Medição) AS DataMedida
    FROM Valor_Sensor_Pressão AS p
        LEFT JOIN Valor_Sensor_Temperatura t USING (Data_Medição)
    WHERE p.ID_Sensor_Pressão = 1
    UNION ALL
    SELECT
        p.Valor_Medido AS pValue,
        t.Valor_Medido AS tValue,
        COALESCE(p.Data_Medição, t.Data_Medição) AS DataMedida
    FROM Valor_Sensor_Temperatura AS t
        LEFT JOIN Valor_Sensor_Pressão AS p USING (Data_Medição)
    WHERE
        p.Data_Medição IS NULL
        AND t.ID_Sensor_Temperatura = 1
    ORDER BY COALESCE(p.Data_Medição, t.Data_Medição)
)

SELECT
    DataMedida,
    COALESCE(LAST_VALUE(ValorPressão) OVER (ORDER BY DataMedida),LAG(ValorPressão) OVER (ORDER BY DataMedida), FIRST_VALUE(ValorPressão) OVER (ORDER BY DataMedida),0) AS ValorPressão,
    COALESCE(LAST_VALUE(ValorTemperatura) OVER (ORDER BY DataMedida), LAG(ValorTemperatura) OVER (ORDER BY DataMedida), FIRST_VALUE(ValorTemperatura) OVER (ORDER BY DataMedida),0) AS ValorTemperatura
FROM Resultado

我的结果是:

"2016-01-01 10:20:00"   "5.5"   "0"
"2016-01-01 10:20:05"   "13"    "1"
"2016-01-01 10:20:06"   "11"    "1"
"2016-01-01 10:20:08"   "11"    "3"
"2016-01-01 10:20:12"   "20"    "20"
"2016-01-01 10:20:13"   "0"     "20"
"2016-01-01 10:21:05"   "100"   "1"
"2016-01-01 10:21:13"   "100"   "31"