【问题标题】:Works in MySQL but fails in Postgresql - having statement [duplicate]在 MySQL 中工作但在 Postgresql 中失败 - 有语句 [重复]
【发布时间】:2020-12-24 07:26:28
【问题描述】:

我有下面的查询,它在 MySQL 中有效,但在 Postgresql 中失败并出现以下错误:

ERROR:  column "status" does not exist

我们如何在 Postgresql 中实现这一点?

select
    devices.*,
    CASE
        WHEN devices.retired = false
        AND devices.last_reported_utc_at > '2020-12-23 07:13:52'
        AND SUM(device_measurements.flow) > 0 THEN 'active'
        WHEN devices.retired = false
        AND devices.last_reported_utc_at > '2020-12-23 07:13:52'
        AND SUM(device_measurements.flow) = 0 THEN 'online'
        WHEN devices.retired = false
        AND devices.last_reported_utc_at <= '2020-12-23 07:13:52' THEN 'offline'
        WHEN devices.retired = false
        AND devices.serial_number IS NULL THEN 'inactive'
        WHEN devices.retired = true THEN 'retired'
    END AS status,
    MAX(devices_meters.activated_at) AS activated_at,
    MAX(devices_meters.created_at) AS latest
from
    devices
    left join devices_meters on devices_meters.device_id = devices.id
    left join device_measurements on device_measurements.device_id = devices.id
group by
    devices.id,
    devices_meters.activated_at
having
    status = "offline"
order by
    devices.installed_at desc

【问题讨论】:

  • 在 SQL 中字符串常量需要用单引号括起来,"offline" 是列引用(在那个上下文中),'offline' 是字符串常量

标签: sql postgresql column-alias


【解决方案1】:

有几种解决方案。

  • 使用子查询
  • 使用 CTE (WITH)
  • 使用横向连接

后者有我的偏好,这是我将如何实现它:

select
    devices.*,
    lt.status,
    MAX(devices_meters.activated_at) AS activated_at,
    MAX(devices_meters.created_at) AS latest
from
    devices
    left join devices_meters on devices_meters.device_id = devices.id
    left join device_measurements on device_measurements.device_id = devices.id
left join lateral (
  SELECT
    CASE
        WHEN devices.retired = false
        AND devices.last_reported_utc_at > '2020-12-23 07:13:52'
        AND SUM(device_measurements.flow) > 0 THEN 'active'
        WHEN devices.retired = false
        AND devices.last_reported_utc_at > '2020-12-23 07:13:52'
        AND SUM(device_measurements.flow) = 0 THEN 'online'
        WHEN devices.retired = false
        AND devices.last_reported_utc_at <= '2020-12-23 07:13:52' THEN 'offline'
        WHEN devices.retired = false
        AND devices.serial_number IS NULL THEN 'inactive'
        WHEN devices.retired = true THEN 'retired'
    END AS status
  ) AS lt ON TRUE
group by
    devices.id,
    devices_meters.activated_at
having
    lt.status = "offline"
order by
    devices.installed_at desc

现在虽然这解决了在查询中随处可用状态的问题,但 GROUP BY 存在另一个问题,它需要包含 devices.* 和 lt.status,但这超出了我认为的这个问题的范围。

【讨论】:

  • 我没有看到解决方案的元素超出了问题的范围
  • 因为问题是“语法是什么?”我不知道devices 表中的列,我也不明白将devices.meters.activated_at 放在GROUP BY 子句中然后检索MAX(activated_at) 的意义。我给出了我能回答的要素,但我觉得我无法比这更好地回答这个问题:-(
  • 你知道其中的一些。你可以用那些。但是,是的,很公平。
  • 嘿@Fabian Pijcke,感谢您的回答。您的查询失败,Query 1: ERROR: aggregate functions are not allowed in FROM clause of their own query level LINE 15: AND SUM(device_measurements.flow) &gt; 0 THEN '...
猜你喜欢
  • 2013-08-26
  • 2012-04-13
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
相关资源
最近更新 更多