У меня есть таблица вроде этого:
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: Извините за английские ошибки, я не американец.
В версиях 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 для каждой "первой строки" на основе упорядочения данных. Как только известная ссылка на строку известна, вы можете отфильтровать любые нежелательные строки.