How to group by DESC order

后端 未结 7 1942
终归单人心
终归单人心 2020-12-03 06:30

I have the following table called questions:

ID | asker 
1  | Bob
2  | Bob
3  | Marley

I want to select each asker only once and if there are

相关标签:
7条回答
  • 2020-12-03 07:26

    Im writing this answer because @Taryn's first/shorter alternative in accepted answer works only if you are exactly selecting just columns used in GROUP BY and MAX. User asking question is selecting all columns in table (he used SELECT *). So when you add another 3rd column to table, that column value in query result will be incorrect. You will get mixed values from different table rows. @Taryn's second/longer alternative (using inner join and subquery) works but query is uselessly complicated and is 5 times slower in my use case than my simple alternative below.


    Consider table questions:

    id | asker 
    -----------
    1  | Bob
    2  | Bob
    3  | Marley
    

    Query SELECT max(id) as id, asker FROM questions GROUP BY asker ORDER BY id DESC returns expected:

    id | asker 
    -----------
    3  | Marley
    2  | Bob
    

    Now consider another table questions:

    id | asker  | other
    -------------------
    1  | Bob    | 1st
    2  | Bob    | 2nd
    3  | Marley | 3rd
    

    Query SELECT max(id) as id, asker, other FROM questions GROUP BY asker ORDER BY id DESC returns unexpected:

    id | asker  | other
    -------------------
    3  | Marley | 3rd
    2  | Bob    | 1st
    

    ... note that value of other for second row of result is incorrect because id=2 comes from second row of table but other=1st comes from first row of table! That is way many users in comments of Taryn's answer reports that this solution does not work.


    Possible simple solution when selecting also another columns is to use GROUP BY + DESC:

    SELECT id, asker, other FROM questions GROUP BY asker DESC

    id | asker  | other
    -------------------
    3  | Marley | 3rd
    2  | Bob    | 2nd
    

    (see demo: https://www.db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/10)

    ... but this simple solution has some limitations:

    • Table must be InnoDB (I think it is not problem because you will get better performance and also since MySQL >= 5.5.5 default/preferred storage engine was changed from MyISAM to InnoDB)
    • You have to create index for column which is used in GROUP BY - so asker in this case (I think it is not problem because you will get better performance since index is suitable in this case. GROUP BY usually needs creation of tmp table but when index is available tmp table will not be created which is faster)
    • For MySQL 5.7 and 8.0 is needed to disable SQL mode ONLY_FULL_GROUP_BY (e.g SET SESSION sql_mode = '';) or use ANY_VALUE() on selected columns which are not aggregated to avoid error ER_WRONG_FIELD_WITH_GROUP.
    • Unfortunately MySQL developers removed support of ASC/DESC withing GROUP BY since MySQL 8.0 https://dev.mysql.com/worklog/task/?id=8693 but fortunately there is alternative GROUP BY col1 ORDER BY col1 ASC/DESC:

    SELECT id, asker, other FROM questions GROUP BY asker ORDER BY asker DESC

    id | asker  | other
    -------------------
    3  | Marley | 3rd
    2  | Bob    | 2nd
    

    (see demo: https://www.db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/11)

    ... result is the same as above with GROUP BY ... DESC (do not forget to use InnoDB and create index).

    0 讨论(0)
提交回复
热议问题