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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库:选择最后一个非空条目相关的知识,希望对你有一定的参考价值。

[这是我一直在绞尽脑汁的问题。假设我有一个表,该表具有一系列时间戳和一个零件号作为主键。该表存储增量更改,这意味着对于每个时间戳,如果字段更改,则记录该更改。如果该字段保持不变,则对于新的时间戳,该字段为NULL。这是基本思想。

 part | timestamp | x-pos | y-pos | status
------+-----------+-------+-------+--------
 a5   |       151 |     5 |    15 |      g
 a5   |       153 |  NULL |    17 |   NULL

(part, timestamp)是主键。第二条记录中的NULL表示自第一条记录以来未更改的值。

我想做的是为按零件分组的每个字段选择最新值。例如,鉴于上述输入,对于a5部分,结果将为153,5,17,g。

截至目前,我已经将此查询合并在一起。

    ((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))

但是这将返回一列,这意味着我可以使用分组依据进行组织。

必须有一种更优雅的处理方式,例如以创造性的方式使用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
;
另一答案

仅一个part,这应该给您一个答案..感谢ruakh

但是我不喜欢这个版本..

SELECT 
    (SELECT timestamp  FROM part_changes WHERE part = $part 
    ORDER BY timestamp DESC
    LIMIT 1) as timestamp,

    (SELECT x-pos FROM part_changes WHERE part = $part and x-pos IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1) as xpos,

    (SELECT y-pos FROM part_changes WHERE part = $part and  y-pos IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1) as ypos,

    (SELECT status FROM part_changes WHERE part = $part and status IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 1)) as status
另一答案

相关时间戳列表:

select max timestamp from part_changes where x_POS is not null group by part

您可以将此视图设为视图:让我们称之为此视图1

SELECT part_changes.part, part_changes.x-pos 
FROM part_changes left join view1 on part_changes.part = view1.part
WHERE x-pos IS NOT NULL 
 AND part_changes.timestamp = view1.timestamp 
GROUP BY part_changes.part

看到我要去哪里?这应该为您提供x-pos的完整列表。

另一答案

ruakh是正确的。替代方法:使用SQL-CLR编写用户定义的聚合。这种聚合可以在您的行上自上而下运行,并记住每列的第一个非空值。

您也可以在应用程序中执行此操作。使您的程序按10个批次的排序顺序请求行。如上所述汇总这些批次。如果在完成当前批次后,出现空列,则获得下一个批次。

另一答案

278O0P [LPKOJIGYWEQ32W3E4R5Y7U8I9OL0P; [P [OIUYTREWQ] >>

以上是关于数据库:选择最后一个非空条目的主要内容,如果未能解决你的问题,请参考以下文章

在片段中显示适当的 SQLite 数据(相同的条目出现在不同的选择条目中)

我想从数据库表中选择最后 5 个条目并将其显示在页面上。如何使用 JSP 实现它?

Doctrine 只选择集合的最后一个条目

在几天的持续时间内,选择表格中记录的每一天的最后一个条目

查询以选择每小时最新的员工条目

如何使用 linq 实体仅从 sql 表中选择最后一个条目