sql – 数据库:选择最后一个非空条目

前端之家收集整理的这篇文章主要介绍了sql – 数据库:选择最后一个非空条目前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是一个我一直在大脑上的问题.假设我有一个表,其中包含一系列时间戳和零件号作为主键.该表存储增量更改,这意味着对于每个时间戳,如果字段更改,则会记录该更改.如果该字段没有更改,那么对于新的时间戳,它为NULL.
这是基本的想法.
part | timestamp | x-pos | y-pos | status
------+-----------+-------+-------+--------
 a5   |       151 |     5 |    15 |      g
 a5   |       153 |  NULL |    17 |   NULL

(部分时间戳)是主键.第二条记录中的NULL表示自第一条记录以来不变的值.

我想要做的是选择由零件分组的每个字段的最新值.例如,给定上述条目,结果将为153,5,17,g部分a5.

到目前为止,我已经把这个黑客一起查询了.

((SELECT x-pos FROM part_changes WHERE x-pos IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1)

    UNION

    (SELECT y-pos FROM part_changesWHERE y-pos IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1)

    UNION

    (SELECT status FROM part_changes WHERE status IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1))

但是这返回一个列,这意味着我可以使用group-by来组织.

必须做一个更优雅的做事方式,比如以创造性的方式使用COALESCE或IS NULL.但我被困住了,无法想像出来.有人有想法吗?

不,我不能改变数据库结构.

编辑:ruakh有正确的想法.现在唯一的问题是逐个分组.我似乎无法绕过LIMIT 1分组多个部分.有任何想法吗?

mdahlman,我不太熟悉postgresql中的分析函数.所以,如果这个解决方案比一个复杂的查询更容易,那么一切都会发布你的想法.

编辑2:感谢大家的帮助.我认为我已经很好地掌握了我需要做的事情.

解决方法

而不是使用UNION,这听起来像您真的希望在列表中的子查询.也就是说,而不是(SELECT …)UNION(SELECT …)UNION(SELECT …),你想要SELECT(SELECT …),(SELECT …),(SELECT …)

例如:

SELECT part,( SELECT x_pos
           FROM part_changes
          WHERE part = pc.part
            AND x_pos IS NOT NULL
          ORDER
             BY timestamp DESC
          LIMIT 1
       ) AS x_pos,( SELECT y_pos
           FROM part_changes
          WHERE part = pc.part
            AND y_pos IS NOT NULL
          ORDER
             BY timestamp DESC
          LIMIT 1
       ) AS y_pos,( SELECT status
           FROM part_changes
          WHERE part = pc.part
            AND status IS NOT NULL
          ORDER
             BY timestamp DESC
          LIMIT 1
       ) AS status
  FROM ( SELECT DISTINCT
                part
           FROM part_changes
       ) AS pc
;

但是在这一点上,我真的会考虑编写一个存储过程.

或者:

SELECT DISTINCT
       part,FIRST_VALUE(x_pos) OVER
         ( PARTITION BY part
               ORDER BY CASE WHEN x_pos IS NULL
                             THEN NULL
                             ELSE TIMESTAMP
                         END DESC NULLS LAST
         ) AS x_pos,FIRST_VALUE(y_pos) OVER
         ( PARTITION BY part
               ORDER BY CASE WHEN y_pos IS NULL
                             THEN NULL
                             ELSE TIMESTAMP
                         END DESC NULLS LAST
         ) AS y_pos,FIRST_VALUE(status) OVER
         ( PARTITION BY part
               ORDER BY CASE WHEN status IS NULL
                             THEN NULL
                             ELSE TIMESTAMP
                         END DESC NULLS LAST
         ) AS status
  FROM part_changes
;
原文链接:https://www.f2er.com/mssql/76003.html

猜你在找的MsSQL相关文章