[英]How to group by similar integer values in Postgres sql?
我有一个非常简单的数据库表,每次扫描产品(RFID 扫描仪)时都会插入一个新条目。
扫描表:
身份证(公钥) | Product_ID (FK) | 创建时间 |
---|---|---|
1个 | 1个 | 2023-01-26 10:39:00.0000 |
2个 | 2个 | 2023-01-26 10:39:02.0000 |
3个 | 3个 | 2023-01-26 10:39:04.0000 |
4个 | 4个 | 2023-01-26 10:47:00.0000 |
我的目标是在产品 ID 被扫描时以指定的容差(以秒为单位)对产品 ID 进行聚类,因此例如对于我表中的条目和 10 秒的容差,所需的结果将是
Product_IDs |
---|
{1, 2, 3} |
{4} |
我第一次尝试解决这个问题是这样的:
SELECT ARRAY_AGG(DISTINCT Product_ID) FROM scans GROUP BY ROUND(EXTRACT(EPOCH FROM created_at) / 10);
这种方法有点奏效,但在极端情况下,例如,当一个产品在第 19 秒被扫描而另一个产品在第 21 秒被扫描时,它不会被组合在一起,尽管它应该被组合在一起。
有什么更好、更可靠的方法来解决这个问题?
如果行之间的时间超过 10 秒,我将假设这些组是分开的。 例如测试数据
create table scans(ID int, Product_ID int, Created_At TimeStamp);
insert into scans values
(1, 1,cast('2023-01-26 10:39:00.000' as TimeStamp))
,(2, 2,cast('2023-01-26 10:39:02.000' as TimeStamp))
,(3, 3,cast('2023-01-26 10:39:11.000' as TimeStamp))
,(4, 4,cast('2023-01-26 10:47:00.000' as TimeStamp))
;
计算当前行和前一行之间的时间差。 当差异大于“10 秒”时 - 即开始新的扫描组。
with ScansDif as(
select *
,Created_At-lag(Created_At,1,Created_At)over(order by Created_At) dif
from scans
)
,ScansGroup as(
select *
,sum(case when dif>cast('10'||' second' as interval) then 1 else 0 end)
over(order by Created_At rows unbounded preceding) grN
from ScansDif
)
SELECT ARRAY_AGG(DISTINCT Product_ID)
FROM ScansGroup
GROUP BY grn
组号
ID | 产品编号 | 创建时间 | 差异 | grn |
---|---|---|---|---|
1个 | 1个 | 2023-01-26 10:39:00 | 00:00:00 | 0 |
2个 | 2个 | 2023-01-26 10:39:02 | 00:00:02 | 0 |
3个 | 3个 | 2023-01-26 10:39:11 | 00:00:09 | 0 |
4个 | 4个 | 2023-01-26 10:47:00 | 00:07:56 | 1个 |
组 0 的第一行和最后一行之间的时间差是 00:11。 结果
array_agg |
---|
{1,2,3} |
{4} |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.