Несколько объединений в одной таблице с подсчетом в одном запросе
У меня есть элементарный вопрос о SQL-запросе с объединением одной и той же таблицы в два раза. Это звучит очень просто, но у меня есть некоторые проблемы с ним. Надеюсь, кто-нибудь может мне помочь в этом вопросе :)
У меня есть две таблицы: "народы" (столбцы: id, имя,...) и "нравится" (id, кто, кто). Люди могут устанавливать "симпатии" друг к другу. Отношения много для многих. Я хочу получить стол с нравами народов: количество полученных "симпатий", доставленных и количество взаимных симпатий. Все правильно, когда я использую только одно соединение. Но для двух объединений (или более) MySQL объединяет все строки (как и ожидалось), и я получаю неправильные значения в подсчетах. Я не знаю, как я должен использовать count/sum/group-by операторами в этом случае :( Я хотел бы сделать это без подзапросов в одном запросе.
Я использовал такой запрос:
SELECT *, count(l1.whom), count(l2.whom)
FROM people p
LEFT JOIN likes l1 ON l1.who = p.id
LEFT JOIN likes l2 ON l2.whom = p.id
GROUP BY p.id;
SELECT p.id, name,
count(lwho.who) delivered_likes,
count(lwhom.whom) received_likes,
count(lmut.who) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON lwhom.id = lwho.id
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id;
Но он подсчитал количество недовольных.
Это проблема только для обучения, и производительность не важна, но я думаю, что три соединения в моем последнем запросе слишком много. Могу ли я сделать это, используя 2 соединения?
Заранее спасибо за помощь.
Я предполагаю, что существует связь 1: N между people
и likes
.
Одна из проблем с вашим вторым запросом, насколько я могу судить, заключается в том, что отношение lwhom
likes
к lwho
с lwho
через id=id
. В основном, lwhom
lwho
. Я бы рекомендовал изменить предложение ON для этой корреляции с lwhom.id = lwho.id
на p.id = lwhom.whom
.
Тем не менее, подсчеты все равно будут влиять на СОЕДИНЕНИЯ. Предположим, что у вас есть столбец идентификатора в таблице likes
, однако, вы могли бы затем каждый COUNT
подсчитать различные одинаковые идентификаторы на человека, а если нет, рассмотрите только использование COUNT(DISTINCT correlation.*)
.
Отклонения в сторону, мы, надеюсь, должны работать:
SELECT p.id, name,
count(distinct lwho.id) delivered_likes,
count(distinct lwhom.id) received_likes,
count(distinct lmut.id) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON p.id = lwhom.whom
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id,p.name;
У меня есть SQL Fiddle здесь.