为没有子查询的已知其他几列选择具有 MAX(column) 的一行

Posted

技术标签:

【中文标题】为没有子查询的已知其他几列选择具有 MAX(column) 的一行【英文标题】:Select one row with MAX(column) for known other several columns without subquery 【发布时间】:2013-01-20 22:52:11 【问题描述】:

我的表格包含用户对不同项目的投票。它有以下字段:

id, user_id, item_id, vote, utc_time

我了解如何为 #item# 获得 #user# 的最后一票,但它使用子查询:

    SELECT votes.*, items.name, items.price
        FROM votes JOIN items ON items.id = votes.item_id
        WHERE user_id = #user# AND item_id = #item#
            AND utc_time = (
                SELECT MAX(utc_time) FROM votes
                WHERE user_id = #user# AND item_id = #item#
            )

它有效,但对我来说看起来很愚蠢......应该有一种更优雅的方式来获得这个记录。我尝试了这里建议的方法,但我还不能让它工作,所以我会感谢你的帮助:How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?

这个问题还有第二部分:Count rows with DISTINCT(several columns) and MAX(another column)

【问题讨论】:

【参考方案1】:

您只需要结果中的一行,即带有MAX(utc_time) 的行。在 mysql 中,有一个 LIMIT 子句,您可以使用 ORDER BY

SELECT votes.*, items.name, items.price
    FROM votes JOIN items ON items.id = votes.item_id
    WHERE user_id = #user# AND item_id = #item#
    ORDER BY votes.utc_time DESC
        LIMIT 1 ;

(user_id, item_id, utc_time)(item_id, user_id, utc_time) 上的索引将有助于提高效率。

【讨论】:

这很聪明...这不是我想要一行,我的表中根本不可能有多个具有这种条件的...不是可能会“慢”吗?或者当 MySQL 看到 LIMIT 1 时,它只会获取最大值而不对整个表进行排序? 如果它可以使用索引,它不会搜索(或排序)整个表(或匹配 WHERE 条件的 N 行)。它将从索引的 (max) 一侧开始并仅获取第一行。 我明白了...是的,我实际上已经有一个索引。谢谢! 有效!知道如何处理这个(同一张桌子:):***.com/questions/14430426/…【参考方案2】:

简单:如果日期/时间是最大日期,则不存在“更高”(更新的)日期/时间(对于相同的 user,item )。

SELECT vo.*
     , it.name, it.price
  FROM votes vo
  JOIN items it ON it.id = vo.item_id
 WHERE vo.user_id = #user# AND vo.item_id = #item#
   AND NOT EXISTS (
       SELECT *
       FROM votes nx
       WHERE nx.user_id = vo.user_id
       AND nx.item_id = vo.item_id
       AND nx.utc_time > vo.utc_time
       );

【讨论】:

它仍然使用子查询...没有办法避免吗? 不,当然不是。甚至窗口函数和 CTE 都会调用子查询(以不同的形式)窗口函数最接近,但 mysql 没有它们。 顺便说一句:一个理智的计划生成器将产生与 LIMIT 子查询相同的计划(给定适当的索引)。非常理智的生成器甚至会识别 MAX() 来生成相同的计划。 BTW2:如果有两条 date=max(date) 的记录,都将找到(因为没有顺序。LIMIT(或 rownumber OVER 窗口)将避免平局。

以上是关于为没有子查询的已知其他几列选择具有 MAX(column) 的一行的主要内容,如果未能解决你的问题,请参考以下文章

具有非零下限的二维数组的子数组

子查询(大查询)中的 SQL 脚本?

选择 Count (distinct col) 查询以显示结果中的行数和列数 - postgresql

从查询到子查询的组中未选择的值

带有子查询的 SQL 查询缓慢

Hibernate - OneToMany 注释导致选择查询的左连接不匹配