MySQL - Как выбрать отдельные строки после заказа и группы?

0

У меня есть таблица вроде этого:

post    |   date    |   tags
--------+-----------+-------
post3   |   2016    |   bbb
post1   |   2018    |   aaa
post2   |   2017    |   ccc
post1   |   2018    |   bbb
post3   |   2016    |   aaa
post2   |   2017    |   bbb
post2   |   2017    |   bbb
post1   |   2018    |   ccc
post3   |   2016    |   ccc

И я хочу получить следующий результат:

post    |   date    |   tags
------- +---------- +--------
post1   |   2018    |   aaa
post2   |   2017    |   bbb
post3   |   2016    |   ccc

Другими словами, я хочу: Во-первых, упорядочить таблицу на основе столбца (который в этом случае является столбцом даты). И, во-вторых, группировать в соответствии с другим столбцом (который в этом случае является тегом столбца). И, наконец, я хочу, чтобы результат столбца не повторялся.

Первая и вторая части я знаю, как это сделать. Я применяю запрос ниже...

SELECT post, 'date', tag
FROM tabela AS t1
WHERE t1.'date' = (
    SELECT MAX(t2.'date') 
    FROM tabela AS t2 
    WHERE t1.tag = t2.tag
) 

... и я получаю следующий результат:

post    |   data    |   tags
------- +---------- +--------
post1   |   2018    |   aaa
post1   |   2018    |   bbb
post1   |   2018    |   ccc

Проблема, как вы можете видеть, в том, что post1 повторяется для всех тегов. И я не хочу, чтобы это произошло. Я хочу, чтобы все строки заполнялись разумно на основе наивысшего значения, заданного столбцом даты, но не повторяющегося в столбце post.

Как я могу это сделать?

PS: Извините за английские ошибки, я не американец.

  • 0
    Я добавил тэг « наибольший n на группу» . Этот тип вопросов часто задают при переполнении стека. Я предлагаю вам следовать метке и посмотреть на некоторые другие решения.
Теги:
select
group-by
sql-order-by
greatest-n-per-group

1 ответ

0
Лучший ответ

В версиях MySQL до v8x вы можете использовать такие переменные:

SELECT
      post, 'date', tags
FROM (
    SELECT
          @row_num :=IF(@prev_value=t.tags, @row_num + 1, 1) AS RowNumber
        , t.post
        , t.'date'
        , t.tags
        , @prev_value := t.tags
    FROM mytable t
    CROSS JOIN (SELECT @row_num :=1,  @prev_value :='') vars
    ORDER BY
          t.tags
          , t.'date' DESC
    ) d
WHERE RowNumber = 1
ORDER BY
      tags, 'date'
;

+----+-------+------+------+
|    | post  | date | tags |
+----+-------+------+------+
|  1 | post1 | 2018 | aaa  |
|  2 | post1 | 2018 | bbb  |
|  3 | post1 | 2018 | ccc  |
+----+-------+------+------+

см.: http://rextester.com/HXQ91572

Для более поздних версий MySQL или таких вариантов, как MariaDb, вы можете просто использовать row_number() over() следующим образом:

SELECT
      post, 'date', tags
FROM (
    SELECT
          t.post
        , t.'date'
        , t.tags
        , row_number() over(partition by t.tags order by t.'date'DESC) as RowNumber
    FROM table1 t
    ) d
WHERE RowNumber = 1
ORDER BY
      tags, 'date'
;

В обоих вариантах запроса выше вы вычисляете значение 1 для каждой "первой строки" на основе упорядочения данных. Как только известная ссылка на строку известна, вы можете отфильтровать любые нежелательные строки.

  • 0
    Работает для моего простого примера выше, но для большой таблицы, к сожалению, нет ...: (((
  • 0
    Мой ответ был отредактирован. Я использовал неправильный столбец для заказа, должны были быть теги и дата (изначально я использовал сообщение и дату)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню