Логика SQL-запросов для начинающих
У меня есть 2 стола: один называется "лайки" с колонками пьющих и пивом, которое им нравится. Другой называется продает со столбцами названий баров и пива, которое они продают.
У меня трудное время с конкретным запросом:
"Drinkers who like every beer served by Bobbys"
Я работал через следующий (некорректный) SQL-запрос:
Select distinct a.drinker
from likes a
where exists
(
select *
from likes b, sells t
where a.drinker = b.drinker
and a.beer = t.beer
and t.bar = 'Bobbys'
);
Но этот запрос возвращает пьющих, которым нравится немного пива, поданного Bobbys, а не все пиво. Пока пьющий любит пиво, подаваемое Bobbys, его имя возвращается, а это не то, о чем говорится в заявлении.
Мне нелегко логично изменить этот запрос, чтобы включить в него только тех пьющих, которым нравится все пиво, подаваемое баром Bobbys, а не только некоторые.
Любая помощь приветствуется. Спасибо.
2 ответа
Этот тип запроса иногда называют реляционным делением, и общее решение этого заключается в том, чтобы использовать двойное отрицание и запрашивать пьющих, для которых не существует пива, которое Bobbys предлагает, кроме тех, которые им нравятся.
Это может быть немного сложно следовать, но логика звучит здраво. Обратите внимание, что в него войдут пьющие, которые могут любить и другие сорта пива, если им нравится все, что подают Бобби.
select distinct drinker
from likes l1
where not exists (
select *
from sells s
where bar = 'Bobbys'
and not exists (
select *
from likes l2
where s.beer = l2.beer
and l2.drinker = l1.drinker
)
);
Моя идея заключается в следующем:
- Получите пиво, поданное Bobbys
- Присоединяйтесь к пьющим с этим пивом, чтобы узнать, какие пьющие любят пиво от Bobbys
- Подсчитайте количество пива, которое нравится каждому пьющему (только пиво, подаваемое Bobbys), и верните тех пьющих, количество которых равно общему количеству пива, подаваемого Bobbys.
Вот запрос:
with bobbysbeers as (select distinct beer from sells where bar = 'Bobbys')
select a.drinker
from likes a, bobbysbeers b
where a.beer = b.beer
group by drinker
having count(distinct a.beer) = (select count(*) from b);