如何在 SQL (postgresql) 中选择每第 n 分钟的行

Posted

技术标签:

【中文标题】如何在 SQL (postgresql) 中选择每第 n 分钟的行【英文标题】:How do I select every nth minute row in SQL (postgresql) 【发布时间】:2020-04-17 06:23:25 【问题描述】:

目前我正在为网络连接的传感器创建仪表板。我正在使用 Blynk + Metabase + PostgreSQL 设置。

我当前在 Metabase 中显示图形的 SQL 命令是:

SELECT ts, extract(hour from ts) as h, extract(minute from ts) as m, extract(second from ts) as s, device_id , pin, doublevalue
FROM "public"."reporting_raw_data"
WHERE device_id = 81224 AND (extract(hour from ts) = 8 OR extract(hour from ts) = 13) AND (extract(minute from ts) = 0) AND (pin BETWEEN 10 AND 13)
ORDER BY ts ASC
LIMIT 43200

SQL 查询的输出:

ts                          |   h|  m|  s       |device_id  |pin|double_value 
=============================================================================
March 23, 2020, 08:00 AM    |   8|  0|  42.21   |81,224     |12 |0
March 23, 2020, 08:00 AM    |   8|  0|  42.33   |81,224     |11 |0
March 23, 2020, 08:00 AM    |   8|  0|  42.35   |81,224     |10 |21.09
March 23, 2020, 08:00 AM    |   8|  0|  44.24   |81,224     |12 |0
March 23, 2020, 08:00 AM    |   8|  0|  44.36   |81,224     |11 |0
March 23, 2020, 13:00 AM    |  13|  0|  45.21   |81,224     |12 |0
March 23, 2020, 13:00 AM    |  13|  0|  48.33   |81,224     |11 |0
March 23, 2020, 13:00 AM    |  13|  0|  33.35   |81,224     |10 |19.31
...

但是,我的目标更像是这样

ts                          |   h|  m|  s       |device_id  |pin|double_value
=============================================================================
March 23, 2020, 08:00 AM    |   8|  0|  42.21   |81,224     |12 |0
March 23, 2020, 08:00 AM    |   8|  0|  42.33   |81,224     |11 |0
March 23, 2020, 08:00 AM    |   8|  0|  42.35   |81,224     |10 |21.09
March 23, 2020, 13:00 AM    |  13|  0|  45.21   |81,224     |12 |0
March 23, 2020, 13:00 AM    |  13|  0|  48.33   |81,224     |11 |0
March 23, 2020, 13:00 AM    |  13|  0|  33.35   |81,224     |10 |19.31
...

如何选择每个 pin 的每第 n 分钟行?

编辑 17/04/2020 - 当前解决方案

SELECT
    MAX(ts) as t,
    pin,
    device_id,
    date(ts) as d,
    extract(hour from ts) as h,
    extract(minute from ts) as m,
    AVG(doublevalue) as value


FROM "public"."reporting_raw_data"
WHERE device_id = 81224 
    AND ( extract(hour from ts) IN (8, 12, 16, 20)) 
    AND extract(minute from ts) = 0
GROUP BY 
    device_id,
    d,
    h,
    m,
    pin
LIMIT 1000

【问题讨论】:

这有帮助吗? Select first row in each GROUP BY group? 在我看来,您想按 pinhm 分组,但只检索每个“组”中的第一行。 谢谢,我设法以某种方式创建了类似的东西。我不是选择每 x 日期时间,而是每 n 次进行一次总结。 【参考方案1】:

您可以使用 DISTINCT ON(),一个 PostgreSQL SQL 扩展(也就是说,它不是标准 SQL 的一部分)。

DISTINCT ON 表达式必须匹配最左边的 ORDER BY 表达式

因此,您使用 DISTINCT ON 的查询将如下所示:

SELECT DISTINCT ON (ts, pin) ts, extract(hour from ts) as h, extract(minute from ts) as m, extract(second from ts) as s, device_id , pin, doublevalue
FROM "public"."reporting_raw_data"
WHERE device_id = 81224 AND (extract(hour from ts) = 8 OR extract(hour from ts) = 13) AND (extract(minute from ts) = 0) AND (pin BETWEEN 10 AND 13)
ORDER BY ts, pin ASC
LIMIT 43200

(我在 SELECT 子句中添加了 DISTINCT ON 并在 ORDER BY 中添加了一列)

DISTINCT ON(ts, pin) 是什么意思,只保留那些对 (ts, pin) 对具有唯一值的行。

有关 DISTINCT ON 的更多信息,请参考PostgreSQL docs。

【讨论】:

我试过了,DISTINCT ON 在时间戳 (ts) 中不起作用,因为我的设备在一分钟内发送了超过 1 个数据。因此每一行的 ts 值都是不同的(也就是不同的)。

以上是关于如何在 SQL (postgresql) 中选择每第 n 分钟的行的主要内容,如果未能解决你的问题,请参考以下文章

如何查看PostgreSQL正在执行的SQL

如何在 PostgreSQL 中选择某一年之后的日期

sql 从PostgreSQL中选择随机行

ORM 的哪些选择允许在“轻按开关”之间更改 RDBMS...SQL Server/SQL Azure 和 PostgreSQL/“云”PostgreSQL

每天将 Postgresql 数据库从小型 SSD 自动备份到多个硬盘

如何编辑我的 postgreSQL 查询以按日期选择几列的最新行