【问题标题】:Using GREATEST in WHERE在 WHERE 中使用 GREATEST
【发布时间】:2017-12-20 01:55:04
【问题描述】:

作为 mysql (MariaDB) 中多辆车的车辆日志的一部分,我需要通过一个查询找到包含每辆车最大里程的行。 该表包含列:id、vehicle_id、km_start、km_end。 所以任务是为每个vehicle_id找到max(max(km_start,km_end))的行。

我发现了

SELECT id 
FROM log 
WHERE (vehicle_id,km_end) IN (SELECT vehicle_id, MAX(IFNULL(km_end,0)) 
                              FROM log 
                              GROUP BY vehicle_id)

如果 km_end 始终存在,将完成这项工作。但是,如果还没有输入 km_end,它将包含 0。因此,最大里程也可以在 km_start 中。

我试过了

SELECT id 
FROM log 
WHERE (vehicle_id,km_max) IN (SELECT vehicle_id, 
                                     GREATEST(MAX(IFNULL(km_start,0)), 
                                              MAX(IFNULL(km_end,0))) AS km_max 
                              FROM log GROUP BY vehicle_id)

返回 错误 1054 (42S22):“IN/ALL/ANY 子查询”中的未知列“km_max”

【问题讨论】:

标签: mysql mariadb greatest-n-per-group


【解决方案1】:

那是因为子查询外部 WHERE 中的值列表应该引用 log 中的字段。您也许可以改用 JOIN:

SELECT id 
FROM log AS l
INNER JOIN (
   SELECT vehicle_id
      , GREATEST(MAX(IFNULL(km_start,0)), MAX(IFNULL(km_end,0))) AS km_max 
   FROM log 
   GROUP BY vehicle_id
) AS lMax
ON l.vehicle_id = lMax.vehicle_id 
AND lMax.km_max IN (l.km_start, l.km_end)

另外,我可能会改变这个 GREATEST(MAX(IFNULL(km_start,0)), MAX(IFNULL(km_end,0)))GREATEST(IFNULL(MAX(km_start,0)), IFNULL(MAX(km_end,0)));我不确定这是否完全重要,但直觉上我认为它可能会获得更好的性能。 大多数聚合函数会忽略空值,仅在遇到空值时才返回空值;因此,您唯一需要担心 null 的时间是在计算最大值之后。 (如果您使用平均值并希望将空值计为 0,那将是另一回事。)


或者,这也可以工作:

WHERE (vehicle_id
       , GREATEST(MAX(IFNULL(km_start,0)), MAX(IFNULL(km_end,0)))
      ) IN (SELECT vehicle_id
                   , GREATEST(MAX(IFNULL(km_start,0)), MAX(IFNULL(km_end,0))) AS km_max 
            FROM log 
            GROUP BY vehicle_id
           )

【讨论】:

  • 非常感谢,Uueerdo。你的第一个提案很有魅力。更改 MAX 和 IFNULL 的顺序会引发 ERROR 1064 (42000):您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,以获取在 '0))、IFNULL(MAX(km_end,0))) AS km_max FROM log GROUP BY vehicle_id) AS lMax ON l' 在第 1 行附近使用的正确语法 你的第二个提案(或者...)抛出 ERROR 1111 (HY000): Invalid use of group function will use the first.
  • Re: 交换 IFNULL 和 MAX;您还需要移动 IFNULL 的第二个参数 ,即IFNULL(MAX(x),0),不是IFNULL(MAX(x,0))。回复:第二个建议;哦,是的,不能在 WHERE 中聚合;您可以输入 HAVING(但有些人会认为在同一上下文中使用没有 GROUP BY 的 HAVING 是对语言的滥用。)
  • 试过 IFNULL(MAX(x),0) 而不是 IFNULL(MAX(x,0))。现在可以了。谢谢。
猜你喜欢
  • 1970-01-01
  • 2015-09-11
  • 2022-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-29
  • 2011-04-17
  • 2020-07-20
相关资源
最近更新 更多