【问题标题】:Specify sorting order for a GROUP BY query to retrieve oldest or newest record for each group为 GROUP BY 查询指定排序顺序以检索每个组的最旧或最新记录
【发布时间】:2010-04-27 15:08:57
【问题描述】:

我需要从升级请求日志表中获取每台设备的最新记录。设备的唯一性取决于其硬件 ID 和 MAC 地址的组合。我一直在尝试使用GROUP BY 执行此操作,但我不相信这是安全的,因为它看起来可能只是返回“最高记录”(无论 SQLite 或 MySQL 认为是什么)。

我曾希望可以通过ORDER BY 来暗示这个“最高记录”,但这似乎没有任何影响,因为以下两个查询为每个设备返回相同的记录,只是顺序相反:

SELECT extHwId,
       mac,
       created
  FROM upgradeRequest
 GROUP BY extHwId, mac
 ORDER BY created DESC

SELECT extHwId,
       mac,
       created
  FROM upgradeRequest
 GROUP BY extHwId, mac
 ORDER BY created ASC

还有其他方法可以做到这一点吗?我看过几篇有些相关的帖子,它们都涉及子选择。如果可能,我想在没有子选择的情况下执行此操作,因为我想学习如何在没有子选择的情况下执行此操作。

【问题讨论】:

  • 三元组extHwId, max, created 是唯一的还是有联系的?
  • 有可能有关系。

标签: sql mysql group-by


【解决方案1】:

试试:

 SELECT extHwId, mac, MAX(created)
 FROM upgradeRequest
 GROUP BY extHwId, mac

【讨论】:

  • +1 由于没有请求该行中的其他字段,因此可以使用简单的 group by。
【解决方案2】:

您不能使用 GROUP BY 来“获取最新的记录”。 GROUP BY 将许多记录聚合在一起,因此您最终看到/提取的不是表中的实际记录,而是由一个或多个表记录构造的“虚拟”记录。

如果您真的想要每台设备的最新记录,则需要使用子查询。但是,如果您只想知道每个设备最近记录的日期,您可以通过在创建的字段周围放置一个 MAX 聚合来使用 GROUP BY:

SELECT
    extHwId, 
    mac, 
    MAX(created)
FROM upgradeRequest
GROUP BY extHwId, mac
ORDER BY created ASC

【讨论】:

  • 正确答案,但是 4 秒太慢了。无论如何我都会给你 +1,因为你花时间提供更多信息。
【解决方案3】:

应该这样做...

SELECT ur.extHwId,
       ur.mac,
       ur.created
 from upgradeRequest ur
  left outer join upgradeRequest ur2
   on ur2.extHwId = ur.extHwId
    and ur2.mac = ur.mac
    and ur2.Created > ur.Created  --  Join with all "later" entries
 where ur2.Created is null  --  Filter out all rows that have any later entries

...但它很尴尬,在大表上可能表现不佳(因为您正在阅读和检查几乎每一行),并且如果有多个条目设置为完全相同的最近日期,则会产生重复.当使用子查询完成时,这种查询效率会高得多,例如以下形式:

SELECT ur.extHwId,
       ur.mac,
       ur.created
 from upgradeRequest ur
 where not exists (select 1
                    from upgradeRequest ur2
                    where ur2.extHwId = ur.extHwId
                     and ur2.mac = ur.mac
                     and ur2.Created > ur.Created)

这里的优点是数据库引擎只需要在子查询中找到 1 行(而不是先读取所有行)来过滤掉一行。

【讨论】:

  • 两个查询通常以相同的执行计划结束(取决于基表上的唯一约束)
猜你喜欢
  • 2014-10-21
  • 2021-11-09
  • 2016-05-15
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
相关资源
最近更新 更多