#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. Если один и тот же идентификатор находится в обеих группах, то клиент, должно быть, купил чай и кофе.