LEFT JOIN только первая строка
Я прочитал много потоков о получении только первой строки левого соединения, но по какой-то причине это не работает для меня.
Вот моя структура (упрощенная, конечно)
Каналы
id | title | content
----------------------
1 | Feed 1 | ...
Художники
artist_id | artist_name
-----------------------
1 | Artist 1
2 | Artist 2
feeds_artists
rel_id | artist_id | feed_id
----------------------------
1 | 1 | 1
2 | 2 | 1
...
Теперь я хочу получить статьи и присоединиться только к первому артисту, и я подумал о чем-то вроде этого:
SELECT *
FROM feeds
LEFT JOIN feeds_artists ON wp_feeds.id = (
SELECT feeds_artists.feed_id FROM feeds_artists
WHERE feeds_artists.feed_id = feeds.id
LIMIT 1
)
WHERE feeds.id = '13815'
чтобы получить только первую строку feeds_artists, но уже это не работает.
Я не могу использовать TOP
из-за моей базы данных, и я не могу сгруппировать результаты по feeds_artists.artist_id
, поскольку мне нужно сортировать их по дате (я получил результаты, группируя их таким образом, но результаты, новейший)
Пробовал что-то с OUTER APPLY, а также не добился успеха.
Честно говоря, я не могу себе представить, что происходит в этих рядах - возможно, самая большая причина, почему я не могу заставить это работать.
РЕШЕНИЕ:
SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
SELECT artist_id
FROM feeds_artists fa
WHERE fa.feed_id = f.id
LIMIT 1
)
WHERE f.id = '13815'
Ответы
Ответ 1
Ответ @Matt Dodges поставил меня на правильный путь. Еще раз спасибо за все ответы, которые помогли многим ребятам. Получилось так:
SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
SELECT artist_id
FROM feeds_artists fa
WHERE fa.feed_id = f.id
LIMIT 1
)
WHERE f.id = '13815'
Ответ 2
Если вы можете предположить, что идентификаторы исполнителя увеличиваются с течением времени, то MIN(artist_id)
будет самым ранним.
Итак, попробуйте что-то вроде этого (untested...)
SELECT *
FROM feeds f
LEFT JOIN artists a ON a.artist_id = (
SELECT
MIN(fa.artist_id) a_id
FROM feeds_artists fa
WHERE fa.feed_id = f.feed_id
) a
Ответ 3
Версия без подзапроса:
SELECT f.title,
f.content,
MIN(a.artist_name) artist_name
FROM feeds f
LEFT JOIN feeds_artists fa ON fa.feed_id = f.id
LEFT JOIN artists a ON fa.artist_id = a.artist_id
GROUP BY f.id
Ответ 4
Версия без подзаголовка, которая присоединится только к первому автору:
SELECT f.title,
f.content,
a.artist_name artist_name,
min(a.id) as m
FROM feeds f
LEFT JOIN feeds_artists fa ON fa.feed_id = f.id
LEFT JOIN artists a ON fa.artist_id = a.artist_id
GROUP BY f.id
HAVING a.id = m;
Ответ 5
Я использовал что-то еще (я думаю, что лучше...) и хочу поделиться этим:
Я создал VIEW, в котором есть предложение "group"
CREATE VIEW vCountries AS SELECT * PROVINCES GROUP BY country_code
SELECT * FROM client INNER JOIN vCountries on client_province = province_id
Я хочу сказать еще, что я думаю, что нам нужно сделать это решение, ПОТОМУ ЧТО МЫ ЧТО-ТО НЕПРАВИЛЬНО ПРИ АНАЛИЗЕ... по крайней мере, в моем случае... но иногда это дешевле сделать, чтобы перепроектировать все...
Я надеюсь, что это помогает!
Ответ 6
Я хочу дать более обобщенный ответ. Тот, который будет обрабатывать любой случай, когда вы хотите выбрать только первый элемент в левом соединении.
Вы можете использовать подзапрос, который GROUP_CONCATS, что вы хотите (отсортированный тоже!), А затем просто разделить результат GROUP_CONCAT и взять только его первый элемент, например так...
LEFT JOIN Person ON Person.id = (
SELECT SUBSTRING_INDEX(
GROUP_CONCAT(FirstName ORDER BY FirstName DESC SEPARATOR "_" ), '_', 1)
) FROM Person
);
Поскольку в качестве опции ORDER BY у нас есть DESC, будет возвращен идентификатор человека для кого-то вроде "Зак". Если бы мы хотели кого-то с таким именем, как "Энди", мы бы изменили ORDER BY FirstName DESC на ORDER BY FirstName ASC.
Это ловко, так как это дает возможность упорядочения полностью в ваших руках. Но после большого тестирования он не будет хорошо масштабироваться в ситуации с большим количеством пользователей и большим количеством данных.
Это, однако, полезно при запуске отчетов с интенсивным использованием данных для администратора.