Выбрать все последние даты из всего списка идентификаторов - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь выбрать все видео, которые были добавлены в последний раз, без повторения какого-либо ID_video_type (столбец id_video_tipo).

Вот пример данных в базе данных:

enter image description here

Я пытаюсь выполнить следующий запрос

SELECT *
FROM `video` 
GROUP BY id_video_tipo
ORDER BY data DESC

но когда я это делаю, я получаю следующий результат

enter image description here

Как вы видите, мне удалось показать видео без повторения id_video_tipo, но я не могу показать видео с последней датой. Например, для id_video_tipo = 6 он должен был показать видео с id = 3. Вместо этого он показывает видео с id = 2. Как я могу это исправить?

Ответы [ 3 ]

1 голос
/ 05 апреля 2020

Вам понадобится использовать ОКНО , чтобы сделать это:

CREATE TABLE video
(
id_video_tipo INT,
data DATETIME
);

INSERT INTO video VALUES (1,'2020-01-01'),(1,'2020-01-02'),(1,'2020-01-03'),(1,'2020-01-04');

SELECT *
FROM
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY id_video_tipo ORDER BY data DESC) AS 'RNum'
    FROM `video` 
) vids
WHERE vids.RNum = 1;

Выше определенно работает в MySQL 8 и выше.

0 голосов
/ 05 апреля 2020

Коррелированный подзапрос - правильный подход. Но если вы хотите гарантировать одну строку в наборе результатов для каждого id_video_tipo - что ваш вопрос явно утверждает - тогда вам нужно быть осторожным. Дубликаты в исходных данных и результат дублирования в наборе результатов.

Решение этого заключается в использовании столбца id:

SELECT v.*
FROM video v
WHERE v.id = (SELECT v2.id
              FROM video v2
              WHERE v2.id_video_tipo = v.id_video_tipo
              ORDER BY v2.data DESC
              LIMIT 1
             );

В MySQL 8+ вы будет использовать row_number() для этой цели, как предлагает Джим Джонсон.

0 голосов
/ 05 апреля 2020

Вы можете сделать это с коррелированным подзапросом в предложении WHERE, который возвращает последнюю дату для каждого id_video_tipo:

SELECT v.*
FROM `video` v
WHERE v.data = (SELECT MAX(data) FROM `video` WHERE id_video_tipo = v.id_video_tipo)

или с NOT EXISTS:

SELECT v.*
FROM `video` v
WHERE NOT EXISTS (
  SELECT 1 FROM `video`
  WHERE id_video_tipo = v.id_video_tipo AND data > v.data
)
...