为没有子查询的已知其他几列选择具有 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) 的一行的主要内容,如果未能解决你的问题,请参考以下文章