小编典典

ORDER BY子查询,用于GROUP BY到JOIN的转换

sql

我有这张table

id |   title   | amount | timestamp
1  |  random1  |   150  | 1313635011
2  |  random2  |   190  | 1313635730
3  |  random2  |   210  | 1313637359
4  |  random2  |   100  | 1313691807
5  |  random3  |   130  | 1313692673
6  |  random4  |   900  | 1313692739
7  |  random4  |   111  | 1313692988

我想得到这个结果(行与不同的标题和最大的时间戳):

id |   title   | amount | timestamp
1  |  random1  |   150  | 1313635011
4  |  random2  |   100  | 1313691807
5  |  random3  |   130  | 1313692673
7  |  random4  |   111  | 1313692988

我有这个查询。

SELECT * FROM (
  SELECT * FROM table ORDER BY timestamp DESC 
) m GROUP BY title

它可以用作魅力,但是可以将其转换为JOIN语句吗?

谢谢


阅读 174

收藏
2021-04-07

共1个答案

小编典典

可以简化为以下内容(ORDER BY子查询中的没用):

SELECT * 
FROM table
GROUP BY title

为什么您认为自己需要JOIN?(好的,这已通过评论解决)。


在对每个标题(具有最大时间戳的行)进行注释之后,这将完成工作:

SELECT t.* 
FROM
    table AS t
  JOIN
    ( SELECT title
           , MAX(timestamp) AS maxts
      FROM table
      GROUP BY title
    ) AS grp
    ON grp.title = t.title
    AND grp.maxts = t.timestamp
ORDER BY t.timestamp DESC

作为记录,您的原始查询:

SELECT * 
FROM 
  ( SELECT * 
    FROM table 
    ORDER BY timestamp DESC 
  ) m
GROUP BY title

可能会 按预期工作,但是: 在MySQL中,它允许您SELECTGROUP BY子句中(或依赖于这些子句)的列表字段中使用,而其中没有任何聚合函数。因此,以上查询将为每个标题返回一个 或多或少的随机
行。实际上,它将返回找到标题的第一行。因此,首先运行子查询(按排序timestamp DESC)将导致首先找到时间戳最大的行。

但是,仅由于(当(如果)时)优化器不了解子查询是无用的,才会发生这种情况。一天升级到MySQL
7.5版后,您的原始查询可以正常运行,并且查询像以前一样停止工作。(因为优化器变得更聪明,并且无需子选择即可将查询翻译成更简单的查询)。

如果MySQL在将来的版本中决定使用符合SQL标准的GROUPBY查询,您甚至可能会发现查询完全停止工作并产生错误。

2021-04-07