在 SQLite 中有效的 SQL Group By 在 Postgres 中无效

Posted

技术标签:

【中文标题】在 SQLite 中有效的 SQL Group By 在 Postgres 中无效【英文标题】:SQL Group By that works in SQLite does not work in Postgres 【发布时间】:2021-06-04 10:34:47 【问题描述】:

此语句在 SQLite 中有效,但在 Postgres 中无效:

SELECT A.*, B.* 
FROM Readings A 
  LEFT JOIN Offsets B ON A.MeterNum = B.MeterNo AND A.DateTime > B.TimeDate 
WHERE A.MeterNum = 1 
GROUP BY A.DateTime 
ORDER BY A.DateTime DESC

读数表包含电分表读数,每个读数都带有日期戳。 Offsets 表保存用户在将故障仪表替换为重新从零开始的新仪表后输入的调整。如果没有 Group By 语句,查询会为每个抄表返回一行,并在读取日期之前进行每次先前的调整,而我只想要最后一次调整。

我在 Group By for Postgres 上看到的所有文档都表明我应该包含一个我不需要也不能使用的聚合函数(读数列包含从仪表返回的 Modbus 字符串)。

【问题讨论】:

嗨,想想看,你想要一个按 A.DateTime 的组,但 pg 不知道你想要什么其他字段。您必须指明如何处理不同的行和相同的 A.DateTime 【参考方案1】:

只需在派生表中选择最新读数即可。在 Postgres 中,这可以使用 distinct on () 非常有效地完成

SELECT A.*, B.* 
FROM readings A 
  left join (
     select distinct on (meterno) o.*
     from offsets o
     order by o.meterno, o.timedate desc
  ) B ON A.MeterNum = B.MeterNo AND A.DateTime > B.TimeDate 
WHERE A.meternum = 1 
ORDER BY A.DateTime DESC

distinct on () 每米只会返回一行,这是由于order by ... , timedate desc 而导致的“最新”行

通过使用lateral join 将datetime > timedate 上的条件推送到派生表中,查询甚至可能更快:

SELECT A.*, B.* 
FROM readings A 
  left join lateral (
     select distinct on (meterno) o.*
     from offsets o
     where a.datetime > o.timedeate 
     order by o.meterno, o.timedate desc
  ) B ON A.MeterNum = B.MeterNo 
WHERE A.meternum = 1 
ORDER BY A.DateTime DESC

【讨论】:

以上是关于在 SQLite 中有效的 SQL Group By 在 Postgres 中无效的主要内容,如果未能解决你的问题,请参考以下文章

获取 SQLite 中 GROUP_CONCAT 的所有 id

核心数据:是不是可以在 group by 中使用自定义功能

Snowflake:SQL 编译错误:不是有效的 group by 表达式

sql单列合并

Python / Sqlite3:使用 GROUP_CONCAT 左连接

Sqlite group_concat 选择“特殊需要”