【问题标题】:GROUP BY having MAX dateGROUP BY 有 MAX 日期
【发布时间】:2013-08-15 19:56:43
【问题描述】:

执行此代码时遇到问题:

SELECT * FROM tblpm n 
WHERE date_updated=(SELECT MAX(date_updated) 
FROM tblpm GROUP BY control_number 
HAVING control_number=n.control_number)

基本上,我想返回每个控制编号的最近日期。上面的查询返回正确的输出,但需要 37 秒。在显示输出之前。

有没有其他的sql子句或命令可以比上面的查询执行得更快?

提前致谢。

【问题讨论】:

    标签: mysql sql optimization greatest-n-per-group


    【解决方案1】:

    另一种不使用group by的方式:

    SELECT * FROM tblpm n 
      WHERE date_updated=(SELECT date_updated FROM tblpm n 
                            ORDER BY date_updated desc LIMIT 1)
    

    【讨论】:

    • 这可能行得通,但它被否决了,因为它是一种非常低效的方法。
    【解决方案2】:

    HAVING 快速简单:

    SELECT * FROM tblpm n 
    FROM tblpm GROUP BY control_number 
    HAVING date_updated=MAX(date_updated);
    

    HAVING 的上下文中,MAX 查找每个组的最大值。只有每组中的最新条目才能满足date_updated=max(date_updated)。如果组内的最新消息相同,则两者都将通过HAVING 过滤器,但GROUP BY 表示只有一个出现在返回的表中。

    【讨论】:

    • 实际上我担心这不能按预期工作,我得到了一个空的查询结果集:select * from order_order_status where order_order_status.order_id = 1 group by order_order_status.order_id having order_order_status.created_at = max(order_order_status.created_at) 表有这些条目:INSERT INTO order_order_status (id, order_id, created_at) VALUES (1, 1, '2016-10-01 01:57:37'), (2, 2, '2016-10-01 01:57:54'), (3, 3, '2016-10-02 02:12:49'), (4, 3, '2016-10-02 02:14:19'), (5, 3, '2016-10-02 04:18:07'), (8, 1, '2016-10-03 01:22:53');
    • Having 子句中的最大值将为您提供整个表中具有最大 date_updated 的行
    【解决方案3】:

    将子查询放在 WHERE 子句中并将其限制为 n.control_number 意味着它会多次运行子查询。这称为相关子查询,它通常是性能杀手。

    最好在 FROM 子句中运行一次子查询,以获得每个控制号的最大日期。

    SELECT n.* 
    FROM tblpm n 
    INNER JOIN (
      SELECT control_number, MAX(date_updated) AS date_updated
      FROM tblpm GROUP BY control_number
    ) AS max USING (control_number, date_updated);
    

    【讨论】:

    • 您的回答只有 8 票赞成...对于像您这样的 percona db master 来说应该很烦人 ;),多亏了您,您在一年前帮助我解决了一个愚蠢的 MySQL SP 错误,或者所以。像您这样的人使 Stack Overflow 可能成为计算机书呆子的最佳资源。
    • @PacketTracer,感谢您的夸奖,积分很有趣,但我更关心的是帮助人们获得好的答案并取得更大的成功。此外,到目前为止,这个问题已经被浏览了超过 9,300 次。我想我可能帮助了很多人,即使他们没有花时间投赞成票。
    • 我在我自己的表和列中使用这个查询,但是 mysql 说:'from 子句'中的未知列'date_updated'知道为什么吗?
    • 任何想知道USING 做什么的人,它只是将列与ON 配对的替代 - 所以在这个例子中,sn-p USING (control_number, date_updated) 等同于ON max.control_number = n.control_number AND max.date_updated = n.date_updated。在使用 Zend 等框架时,这是一个很好的知识,它使用后者格式而不是前者。
    【解决方案4】:

    没有必要在那个子查询中分组...一个 where 子句就足够了:

    SELECT * FROM tblpm n
    WHERE date_updated=(SELECT MAX(date_updated)
        FROM tblpm WHERE control_number=n.control_number)
    

    另外,您在“date_updated”列上有索引吗?这肯定会有所帮助。

    【讨论】:

    • 如果更新日期相同(并列),使用此方案时会同时显示两条记录,所以必须添加GROUP BY n. control_number
    • 如果您需要性能,请不要使用此技术,请阅读 Bill answer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 2010-11-20
    • 2012-10-30
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多