Запросите SQL-запрос, который очень сложен для меня

#sql

#sql

Вопрос:

Есть кофейня, в которой продаются напитки. каждой проданной чашке напитка будет присвоен уникальный идентификатор.

Предположим, что у всех клиентов кофейни есть идентификаторы участников магазина (все они уникальны).

Напитки в магазине можно разделить на 2 типа: либо кофе, либо чай.

Теперь у меня есть 4 таблицы.

  • Член (MemberID, MemberName)

  • Beverage(bID, CustomerID) (CustomerID ссылается на Member.MemberID) <- иметь один объект beverage для каждой проданной чашки.

  • Coffee(coffeeName, ставка) (ставка, ссылающаяся на Beverage.bID)

  • Tea (teaName, bID) (ставка, ссылающаяся на Beverage.bID)

Чай и кофе являются подтипами напитков.

Также каждый участник может покупать разные напитки много раз.

Найдите SQL-запрос, который может отображать всех участников, которые купили оба вида напитков (т. Е. Не Учитывайте участника, который покупает только один вид напитка).

Я думал об этом вопросе около половины дня … надеюсь, кто-нибудь сможет мне помочь.

Комментарии:

1. Что вы пробовали до сих пор?

2. Если у вас есть какое- либо влияние на структуру базы данных, я бы настоятельно рекомендовал объединить таблицы Coffee и Tea.

Ответ №1:

 select
  memberID
from
  Member
where
  memberID IN (select customerID
                 from Beverage inner join Coffee on Beverage.bID = Coffee.bID)
AND
  memberID IN (select customerID
                 from Beverage inner join Tea on Beverage.bID = Tea.bID)
  

или использование EXISTS

 select
  memberID
from
  Member
where
  exists (select *
            from Beverage inner join Coffee on Beverage.bID = Coffee.bID
           where Beverage.customerID = Member.memberID)
AND
  exists (select *
            from Beverage inner join Tea on Beverage.bID = Tea.bID
           where Beverage.customerID = Member.memberID)
  

В зависимости от набора данных существующий вариант может быть быстрее. Предполагая, что необходимые индексы присутствуют, это позволит оптимизатору сократить время при оценке существующих проверок.

Комментарии:

1. Зачем беспокоиться и тратить подзапросы, когда простое внутреннее соединение выполнит ту же работу более эффективно?

2. @StevieG: В некоторых базах данных where exists предложение гарантирует, что запрос проверяет только первое вхождение соответствующей записи, тогда join как предложение будет соответствовать всем соответствующим записям. При таких обстоятельствах exists предложение может быть намного быстрее.

3. @StevieG. Я сделал это с помощью подзапроса, потому что решение join не будет работать (см. Мой комментарий к вашему ответу). Вы могли бы сделать это с помощью joins, присоединившись к таблице напитков дважды, но я предполагаю, что эта таблица будет очень большой, и хотел избежать перекрестного присоединения к очень большой таблице.

Ответ №2:

Вы можете просто присоединиться к обеим таблицам, любой участник, который не купил оба типа, будет исключен объединением..

 select
  distinct m.memberID
from
  Member m 
  INNER JOIN Beverage b ON  m.memberID = b.customerID
  INNER JOIN Beverage b1 ON m.memberID = b1.customerID
  INNER JOIN Coffee c ON b.bID = c.bID
  INNER JOIN Tea t ON b1.bID = t.bID
  

Комментарии:

1. Это не сработает. Соединение с напитком ищет транзакцию с чаем и транзакцию с кофе в одной и той же записи (фактически b.bid = c.bid = t.bid). Это никогда не может быть выполнено (если только не будет напитков с чаем и кофе с одинаковой ставкой, что приведет ко всевозможным другим проблемам)

Ответ №3:

 SELECT DISTINCT m.memberName
FROM Member m
  INNER JOIN (
    SELECT b1.customerID 
    FROM Beverage b1
      INNER JOIN Coffee c ON b1.bID = c.bID
  ) bc ON m.memberID = bc.customerID
  INNER JOIN (
    SELECT b2.customerID 
    FROM Beverage b2
      INNER JOIN Tea t ON b2.bID = t.bID
  ) bt ON m.memberID = bt.customerID
  

Комментарии:

1. Это не сработает. Соединение с напитком ищет транзакцию с чаем и транзакцию с кофе в одной и той же записи (фактически b.bid = c.bid = t.bid). Это никогда не может быть выполнено (если только не будет напитков с чаем и кофе с одинаковой ставкой, что приведет ко всевозможным другим проблемам)

2. @njreed.myopenid.com ты прав. просто попытался сейчас найти еще одно решение. PS Ваше решение с EXISTS очень умное.

Ответ №4:

 Select Distinct m.MemberName,m.MemerID from Member m 
where m.MemerID In
    (Select     b1.CustomerID
    FROM Beverage b1 InnerJoin Coffee c On b1.bID=c.bID
    where b1.CustomerID In
        (Select b2.CustomerID
        From Beverage b2 InnerJoin Tea t On b2.bID=t.Bid))
  

Ответ №5:

Просто искал какой-то сложный запрос, и этот вопрос выскочил (не так сложно, но я попробую), поэтому я просто показываю свое решение:

 select distinct b.customer_id 
from beverage b, coffe c
where b.bid = c.bid
intersect
select distinct b.customer_id 
from beverage b, tea t
where b.bid = t.bid;
  

если вам нужно получить имя клиента, просто добавьте join в customer id = memeberid.

В этом решении вы найдете всех клиентов, которые купили хотя бы 1 кофе, затем вы ищете всех клиентов, которые купили хотя бы 1 чай. Теперь из обеих этих групп кустомеров вы взяли только тот, который имеет тот же идентификатор, что и у intersect. Если один и тот же идентификатор находится в обеих группах, то клиент, должно быть, купил чай и кофе.