Логика 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
    )
);

Образец SQL Fiddle

Моя идея заключается в следующем:

  1. Получите пиво, поданное Bobbys
  2. Присоединяйтесь к пьющим с этим пивом, чтобы узнать, какие пьющие любят пиво от Bobbys
  3. Подсчитайте количество пива, которое нравится каждому пьющему (только пиво, подаваемое 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);
Другие вопросы по тегам