在没有子查询的MySQL中优先使用ORDER BY而不是GROUP BY

时间:2011-01-17 18:14:57

标签: sql mysql group-by sql-order-by subquery

我有以下查询可以执行我想要的操作,但我怀疑可以在没有子查询的情况下执行此操作:

  SELECT * 
    FROM (SELECT * 
            FROM 'versions' 
        ORDER BY 'ID' DESC) AS X 
GROUP BY 'program'

我需要的是按程序分组,但返回具有最高值“ID”的版本中对象的结果。

在我过去的经验中,像这样的查询应该在MySQL中工作,但出于某种原因,它不是:

  SELECT * 
    FROM 'versions' 
GROUP BY 'program' 
ORDER BY MAX('ID') DESC

想要做的是让MySQL首先执行ORDER BY然后然后执行GROUP BY,但是它坚持首先执行GR​​OUP BY,然后执行ORDER BY 。即它正在对分组的结果进行排序,而不是对排序的结果进行分组。

当然不可能写

SELECT * FROM 'versions' ORDER BY 'ID' DESC GROUP BY 'program'

感谢。

3 个答案:

答案 0 :(得分:3)

根据定义,ORDER BY在分组后用处理。根据定义,处理任何SELECT语句的概念方式是:

  1. 计算FROM子句中引用的所有表的笛卡尔积。
  2. 应用FROM子句中的连接条件来过滤结果
  3. 在WHERE子句中应用过滤条件以进一步过滤结果
  4. 根据GROUP BY子句将结果分组为子集,将结果折叠为每个此类子集的单行,并计算任何聚合函数的值 - SUM()MAX(),{{ 1}}等等 - 对于每个这样的子集。请注意,如果未指定GROUP BY子句,则结果将被视为存在单个子集,并且任何聚合函数都应用于整个结果集,并将其折叠为单个行。
  5. 根据HAVING子句过滤现在分组的结果。
  6. 根据ORDER BY子句对结果进行排序。
  7. 具有GROUP BY子句的SELECT结果集中允许的唯一列当然是

    • GROUP BY子句中引用的列
    • 汇总函数(例如AVG()
    • 字面/常数
    • 表达来自上述任何一种情况。

    只有破坏的SQL实现允许MAX()之类的东西 - 对colulmsn a,b和c的引用是无意义/未定义的,因为各个组已折叠为单行,

答案 1 :(得分:2)

SELECT  v.*
FROM    (
        SELECT  DISTINCT program
        FROM    versions
        ) vd
JOIN    versions v
ON      v.id = 
        (
        SELECT  vi.id
        FROM    versions vi
        WHERE   vi.program = vd.program
        ORDER BY
                vi.program DESC, vi.id DESC
        LIMIT 1
        )

(program, id)上创建一个索引,以便快速工作。

关于您的原始查询:

SELECT * FROM 'versions' GROUP BY 'program' ORDER BY MAX('ID') DESC

此查询不会在SQL以外的任何MySQL方言中进行解析。

它滥用MySQLGROUP BY语句返回未分组和未分页表达式的能力。

答案 2 :(得分:2)

只要在(program,id)上有复合索引,就应该这样做并且工作得很好。子查询应该只检查每个程序分支的第一个id,并快速从外部查询中检索所需的记录。

select v.*
from
(
    select program, MAX(id) id
    from versions
    group by program
) m
inner join versions v on m.program=v.program and m.id=v.id