Search code examples
mysqlmaxsql-order-bywhere-clause

Select where max MySQL


Help, please make SQL select to database. There are such data.

My table is:

id  news_id  season  seria   date_update
---|------|---------|-----|--------------------
1  | 4    | 1       | 7   | 2017-04-14 16:38:10
2  | 4    | 1       | 7   | 2017-04-14 17:38:10
5  | 4    | 1       | 7   | 2017-04-14 16:38:10
3  | 4    | 1       | 7   | 2017-04-14 16:38:10
4  | 4    | 1       | 7   | 2017-04-14 16:38:10
6  | 4    | 1       | 7   | 2017-04-14 16:38:10
7  | 4    | 1       | 7   | 2017-04-14 16:38:10
8  | 1    | 1       | 25  | 2017-04-23 18:42:00

Need to get all cells grouped by max season and seria and date and sorted by date_update DESC.

In result I need next rows

id  news_id  season  seria   date_update
---|------|---------|-----|--------------------
8  | 1    | 1       | 25  | 2017-04-23 18:42:00
2  | 4    | 1       | 7   | 2017-04-14 17:38:10

Because these rows have the highest season and seria and date_update per One news_id. i.e I need to select data which have highest season and seria and date_update grouped by news_id and also sorted by date_update DESC

I tried so, but the data is not always correct, and it does not always for some reason cover all the cells that fit the condition.

SELECT serial.* 
FROM serial as serial 
INNER JOIN (SELECT id, MAX(season) AS maxseason, MAX(seria) AS maxseria FROM serial GROUP BY news_id) as one_serial 
ON serial.id = one_serial.id 
WHERE serial.season = one_serial.maxseason AND serial.seria = one_serial.maxseria 
ORDER BY serial.date_update 

Please, help. Thanks.


Solution

  • The specification is unclear.

    But we do know that the GROUP BY news_id clause is going collapse all of the rows with a common value of news_id into a single row. (Other databases would throw an error with this syntax; we can get MySQL to throw a similar error if we include ONLY_FULL_GROUP_BY in the sql_mode.)

    My suggestion would be to remove the GROUP BY news_id clause from the end of the query.

    But that's just a guess. It's not at all clear what you are trying to achieve.

    EDIT

     SELECT t.* 
       FROM ( 
              SELECT r.news_id
                   , r.season
                   , r.seria
                   , MAX(r.date_update) AS max_date_update
                FROM ( 
                       SELECT p.news_id
                            , p.season
                            , MAX(p.seria) AS max_seria
                         FROM ( 
                                SELECT n.news_id
                                     , MAX(n.season) AS max_season
                                  FROM serial n 
                                 GROUP BY n.news_id
                              ) o
                         JOIN serial p
                           ON p.news_id = o.news_id
                          AND p.season  = o.max_season
                     ) q
                JOIN serial r
                  ON r.news_id = q.news_id
                 AND r.season  = q.season
                 AND r.seria   = q.max_seria
             ) s
        JOIN serial t      
          ON t.news_id     = s.news_id
         AND t.season      = s.season
         AND t.seria       = s.seria
         AND t.date_update = s.max_date_update
       GROUP BY t.news_id
       ORDER BY t.news_id 
    

    Or, an alternate approach making use of MySQL user-defined variables...

     SELECT s.id
          , s.season
          , s.seria
          , s.date_update 
       FROM ( 
              SELECT IF(q.news_id = @p_news_id,0,1) AS is_max
                   , q.id
                   , @p_news_id := q.news_id AS news_id
                   , q.season
                   , q.seria
                   , q.date_update
                FROM ( SELECT @p_news_id := NULL ) r
               CROSS
                JOIN serial q
               ORDER
                  BY q.news_id     DESC
                   , q.season      DESC
                   , q.seria       DESC
                   , q.date_update DESC
            ) s
      WHERE s.is_max
      ORDER BY s.news_id