Предположим, у меня есть следующие таблицы:
Проекты
- id INT
- имя VARCHAR
- owner_id INT
версия
- id INT
- project_id INT
- тег VARCHAR
- made_at DATETIME
Владельцы
Я хотел бы получить набор проектов, и я хотел бы присоединиться только к самой новой версии для каждого проекта. Запрос DISTINCT не подходит для этой цели, поскольку он ограничивает столбцы, возвращаемые запросом, однако мне нужны все столбцы.
Вот что я придумал:
SELECT
projects.id, projects.name, projects.owner_id
FROM
projects
INNER JOIN
(SELECT versions.id, versions.project_id, versions.created_at, versions.tag FROM versions ORDER BY versions.created_at DESC LIMIT 1)
ON
projects.id = versions.project_id
WHERE
projects.owner_id = 1
В целом, я хотел бы вернуть ограниченное количество объединенных результатов на основе определенных критериев.
Но мне интересно, есть ли лучшее решение для этого? Вложенный запрос не выглядит элегантным и, вероятно, неэффективным. В первую очередь я ищу решение, совместимое с SQLite, но если есть более подходящие способы для других механизмов SQL, я тоже заинтересован в этом, поскольку в прошлом уже сталкивался с этой проблемой, например, в MySQL.
ОБНОВЛЕНИЕ: Я хотел бы дать дополнительную иллюстрацию проблемы с неправильным решением. Самый простой способ сделать это:
SELECT
projects.id, projects.name, versions.tag, versions.created_at
FROM
projects
INNER JOIN
versions
ON
projects.id = versions.project_id
WHERE
projects.owner_id = 1
ORDER BY
versions.created_at DESC;
Это просто простая структура JOIN. Предположим, в результате будет получен следующий набор данных:
# id name tag created_at
1 1 project1 v2.3 2018-05-08 18:33:42
2 5 project5 v4.0 2018-05-08 11:19:07
3 3 project3 v1.8 2018-05-07 21:41:49
4 5 project5 v3.18 2018-05-07 07:00:26
5 8 project8 v3.12 2018-05-06 08:59:01
6 11 project11 v1.9 2018-05-05 14:27:31
7 5 project5 v3.17 2018-05-04 11:48:22
8 1 project1 v2.2 2018-05-04 05:11:46
9 2 project2 v5.5 2018-05-03 23:08:57
10 7 project7 v6.8 2018-05-03 12:17:33
Решение неверное, поскольку оно также возвращает ненужные строки. Из этого набора данных мне понадобится строка 1, 2, 3, 5, 6, 9, 10.
Потому что он упорядочен по полю versions.created_at в порядке убывания, и мне нужен первый результат, то есть самый последний из каждого проекта.
Вот почему мне понадобится какой-то «селективный LIMIT», который учитывает поле versions.project_id, так же как и запрос SELECT DISTINCT, однако мне нужно вернуть почти все поля из таблицы, не только versions.project_id.
Мне интересно, есть ли "известное" решение этой проблемы, о котором я не знаю?