How to apply ORDER to GROUP BY

forsberg :

I have the article table, each having a related category (or NULL if not categorized - these articles don't interest me in this case).

I want to get 8 newest articles each from one category in a way that there is always only one article for one category (i.e. never 2 articles from the same category).

This query almost work:

SELECT article.id, article.title, category_container.title  FROM `article`
JOIN `category_container` ON category_container.id = article.category_id
WHERE `category_id` IS NOT NULL GROUP BY `category_id` ORDER BY article.created_at DESC LIMIT 8

The problem is, ORDER doesn't work. I want newest, it returns me the earliest ones (with the smallest id, while it should be the opposite).

So, how to apply ORDER to GROUP BY?

Gordon Linoff :

You don't. Your query is broken -- and in the latest versions of MySQL you would properly get an error.

Instead use a filtering method to get the latest rows. Here is a method using a correlated subquery:

SELECT a.id, a.title, cc.title
FROM article a JOIN
     category_container cc
     ON cc.id = a.category_id
WHERE a.created_at = (SELECT MAX(a2.created_at)
                      FROM article a2
                      WHERE a2.category_id = a.category_id
                     )
ORDER BY a.created_at DESC
LIMIT 8;

For performance, you want an index on article(category_id, created_at).

In the more recent versions, this would be even simpler using ROW_NUMBER():

SELECT a.id, a.title, cc.title
FROM (SELECT a.*,
             ROW_NUMBER() OVER (PARTITION BY a.category_id ORDER BY a.created_at DESC) as seqnum
      FROM article a
     ) a JOIN
     category_container cc
     ON cc.id = a.category_id
WHERE seqnum = 1;

Given that your query runs with no errors, you are probably using an older version of MySQL and this won't work.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=297771&siteId=1