繁体   English   中英

检索只有最后一个唯一条目与 postgresql 中的条件匹配的 SQL 记录

[英]Retrieve SQL records where only the last unique entries match criteria in postgresql

我有一张长表,用于跟踪历史上“设备”集合的数字“状态”值(0=新,1=设置模式,2=退休,3=活动,4=非活动)。 这些设备可能在一年中被激活/停用,因此该表是状态变化的连续集合 - 主要是状态 3 和 4,按 id 排序,最后带有时间戳,例如:

     id    | device_id | new_state |        when         
 ----------+-----------+-----------+----------------------------
 218010581 |      2505 |         0 | 2022-06-06 16:28:11.174084
 218010580 |      2505 |         1 | 2022-06-06 16:28:11.174084
 218010634 |      2505 |         3 | 2022-06-06 16:29:25.129019
 218087737 |       659 |         3 | 2022-06-07 22:55:48.705208
 218087744 |      1392 |         3 | 2022-06-07 22:55:59.016974
 218087757 |      1556 |         3 | 2022-06-07 22:56:09.811876
 218087758 |      2071 |         1 | 2022-06-07 22:56:20.850095
 218087765 |      2071 |         3 | 2022-06-07 22:56:29.122074

当我想查找设备列表并查看它们的“历史记录”时,我知道我可以使用以下内容:

select * 
from devstatechange 
where device_id = 2345 
order by "when";

    id     | device_id | new_state |            when            
-----------+-----------+-----------+----------------------------
 184682659 |      2345 |         0 | 2021-05-27 17:03:36.894429
 184682658 |      2345 |         1 | 2021-05-27 17:03:36.894429
 184684721 |      2345 |         3 | 2021-05-27 17:31:01.968314
 194933399 |      2345 |         4 | 2021-08-31 23:30:05.555407
 195213746 |      2345 |         3 | 2021-09-03 16:53:39.043005
 206278232 |      2345 |         4 | 2021-12-31 22:30:08.820068
 206515355 |      2345 |         3 | 2022-01-03 16:06:01.223759
 215709888 |      2345 |         4 | 2022-04-30 23:30:30.309389
 215846807 |      2345 |         3 | 2022-05-02 19:40:31.525514


select * 
from devstatechange 
where device_id = 2351 
order by "when";

    id     | device_id | new_state |            when            
-----------+-----------+-----------+----------------------------
 186091252 |      2351 |         0 | 2021-06-09 15:36:02.775035
 186091253 |      2351 |         1 | 2021-06-09 15:36:02.775035
 186091349 |      2351 |         3 | 2021-06-09 15:37:56.965599
 197880878 |      2351 |         4 | 2021-09-30 23:30:06.691835
 197945073 |      2351 |         3 | 2021-10-01 15:32:35.907913
 208981857 |      2351 |         4 | 2022-01-31 22:30:09.521694
 209722639 |      2351 |         3 | 2022-02-09 15:20:12.412816
 217666572 |      2351 |         4 | 2022-05-31 23:30:30.881928

我真正要寻找的是一个返回唯一设备列表的查询,其中每个设备的最新日期条目包含状态“4” (“非活动状态”),不包括不匹配的记录。

因此,在使用上述数据样本时,即使设备 2345 和 2351 在其整个历史中都具有状态 3 和 4,但只有设备 2351 的最后一个日期条目的状态为 4——这意味着它当前处于“非活动”状态。 设备 2345 不会出现在结果集中,因为其最后一个日期条目的状态为 3 - 它仍然处于活动状态。

在黑暗中刺伤,我尝试了以下变体:

SELECT DISTINCT * 
FROM devstatechange 
WHERE MAX("when") AND new_state = 4 
ORDER BY "when";

SELECT DISTINCT device_id, new_state, MAX("when") 
FROM devstatechange 
WHERE new_state = 4  
ORDER BY "when";

显然没有成功。

我想我可能需要将条目“分组”在一起,但我不知道如何在 SQL 或者更确切地说是 PostgreSQL 中指定“当 new_state = 4 时返回最后一个条目”。

任何正确方向的花絮或戳将不胜感激。

SELECT * FROM (
  SELECT DISTINCT ON (device_id)
  *
  FROM devstatechange
  ORDER BY device_id, "when" DESC
) AS latest
WHERE new_state = 4;

DISTINCT ON关键字与ORDER BY将拉取每个设备的最新行。 外部查询然后根据您的条件过滤这些。

您可以将Row_Number()函数与device_id分区和when排序一起使用。

尝试以下CTE

with cte as 
(
  Select id ,device_id ,new_state  ,when_ ,
  row_number() over (partition by device_id order by when_ desc) as rn
  from devstatechange
)
select * from cte where rn=1 and new_state=4

请参阅db-fiddle的演示。

问题在于:

SELECT DISTINCT * FROM devstatechange WHERE MAX("when") AND new_state=4 ORDER BY "when";

是 MAX("when") 指的是表上的所有条目。

您应该将其更改为:

when = (select max(when) from devstatechange dev2 where dev2.device_id = dev1.device_id )

您可以使用 CTE 获取每个设备的最后一个状态,然后只选择最后一个状态为4的那些,像这样

WITH device_last_state AS (
    SELECT DISTINCT ON (device_id)
        id,
        device_id, 
        last_value (new_state) over (partition by device_id order by "when" desc) as new_state, 
        "when" 
    FROM devicestatechange
)
SELECT * FROM device_last_state
WHERE new_state = 4

检查演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM