вопрос по SQL-запросу - PullRequest
       0

вопрос по SQL-запросу

4 голосов
/ 03 апреля 2011

Я работаю над небольшим проектом, включающим базу данных Oracle, и у меня есть следующие таблицы:

CUSTOMER ( Cid, CName, City, Discount )
PRODUCT ( Pid, PName, City, Quantity, Price )
ORDERS ( OrderNo, Month, Cid, Aid, Pid, OrderedQuantity, Cost )

Как получить имена всех клиентов, которые заказали все продукты?

Например, если клиент x заказал product1, product2 и product3 (все продукты, которые предлагает компания), он будет выбран. И если клиент y только заказал продукт 1 и 2, но не 3, он не будет выбран.

Как мне этого добиться?

Ответы [ 2 ]

5 голосов
/ 03 апреля 2011

Вы хотите "реляционное деление".

select *
  from customer c
 where not exists( -- There are no product
          select 'x'
            from product p
           where not exists(  -- the customer did not buy
                    select 'x'
                      from orders o
                     where o.cid = c.cid 
                       and o.pid = p.id));

или

select c.cid
      ,c.name
  from customer c
  join orders   o using(cid)
 group
    by c.id
      ,c.name
having count(distinct o.pid) = (select count(*) from product);

Вот отличная статья Джо Селко, в которой показано несколько способов реализации реляционного деления (и вариантов): Разделенное мы стоим: SQL реляционного деления

2 голосов
/ 03 апреля 2011

Вы можете использовать group by и использовать условие having, чтобы потребовать, чтобы клиент заказал все имеющиеся продукты:

select  c.CName
from    Customers c
join    Orders o
on      o.Cid = c.Cid
group by
        c.Cid
,       c.CName
having  count(distinct o.Pid) = (select count(*) from products)

ИМХО более читабельно, чем подход "реляционного деления", но меньшеэффективный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...