2014-10-24 8 views
2

У меня есть таблица подписных записей для людей, подписавшихся на группы. Есть столбец groupid и столбец userid (в дополнение к идентификатору первичного ключа). Я хочу найти все строки подписки людей, подписавшихся на группу 1, у которых также нет записи подписки для группы 2. Я думал, что могу использовать шаблон анти-объединения, но я не могу заставить его работать. Я пробовал:Postgres - Left Join, та же таблица

SELECT 
* 
FROM subs s1 
LEFT JOIN subs s2 ON s1.groupid=1 AND s2.groupid=2 AND s1.userid=s2.userid 
WHERE s2.id IS NULL; 

Но это не работает (он возвращает подписные записи с группами, которые не являются 1).

ответ

3

Я хотел бы использовать group by для этого:

select s.userid 
from subs s 
group by s.userid 
having sum(case when s.groupid = 1 then 1 else 0 end) > 0 and 
     sum(case when s.groupid = 2 then 1 else 0 end) = 0; 

Каждое условие в предложении having подсчитывает записи для одной из групп. Первое условие говорит, что есть хотя бы одна строка с groupid = 1. Второй говорит, что нет записей с groupid = 2.

Вы можете делать то, что вы хотите, с помощью left join. Вот такой подход:

SELECT s1.* 
FROM subs s1 LEFT JOIN 
    subs s2 
    ON s1.userid = s2.userid AND s2.groupid = 2 
WHERE s1.groupid = 1 AND s2.id IS NULL; 

Потому что это left join, условие на первые таблицы должны идти в пункте where.

Смежные вопросы