Выберите клиентов, которые приобрели один конкретный продукт - PullRequest
0 голосов
/ 22 апреля 2019

У нас есть две таблицы:

  1. Клиенты:

enter image description here

Продукты:

enter image description here

Цель состоит в том, чтобы выбрать [Id] и [CustomerName] из клиентов, которые приобрели молоко AND не купил Хлеб.В случае, если правильный запрос должен вернуть клиента с идентификатором 2 (Ann).

Запрос, о котором я подумал (и который, очевидно, неверен):

select CustomerName from dbo.Customers
where Id in 
(
  select CustomerId from dbo.Products
  where ProductName = 'Milk' and ProductName != 'Bread'
)

Возвращает дваклиенты: 1 (Джон) и 2 (Энн).Как переписать запрос, чтобы он возвращал только клиента с идентификатором 2?

Ответы [ 5 ]

3 голосов
/ 22 апреля 2019

Вы можете попробовать запрос ниже

SELECT CustomerName 
FROM dbo.Customers c
WHERE EXISTS (
    SELECT 1
    FROM dbo.Products
    WHERE CustomerId = c.Id
        AND ProductName = 'Milk'
) AND NOT EXISTS (
    SELECT 1
    FROM dbo.Products
    WHERE CustomerId = c.Id
        AND ProductName = 'Bread'
)
1 голос
/ 22 апреля 2019

Я склонен использовать агрегацию для этого. Вот один из методов:

select c.customerId
from dbo.Products p
where p.productName in ('Milk', 'Bread')
group by c.customerId
having sum(case when p.productName = 'Milk' then 1 else 0 end) > 0 and
       sum(case when p.productName = 'Bread' then 1 else 0 end) = 0 ;

Вы можете добавить join, чтобы получить имя клиента, если оно вам действительно нужно.

В основном, это подсчитывает количество строк для каждого клиента, которые имеют 'Milk'. > 0 говорит, что есть хотя бы один. Затем он подсчитывает количество строк, которые имеют 'Bread'. = 0 говорит, что их нет.

1 голос
/ 22 апреля 2019

Вам не нужно использовать два exists, просто используйте предложение where с not exists:

select c.*
from customer c
where ProductName = 'Milk' and
      not exists (select 1 from Products p where p.CustomerId = c.id and p.ProductName = 'Bread');
0 голосов
/ 22 апреля 2019

Если нормализация не так, эффективность тоже не так. Вот, пожалуйста:

select CustomerName from dbo.Customers
where
   Id in (select CustomerId from dbo.Products where ProductName = 'Milk')
   and Id not in (select CustomerId from dbo.Products where ProductName = 'Bread')

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

0 голосов
/ 22 апреля 2019
SELECT P.Id ,C.Customers 
FROM Customers AS C , Product AS P
WHERE (C.Id = P.CustomerId)
AND (P.ProductName = 'Milk') 
AND NOT EXISTS (
    SELECT 1
    FROM Products
    WHERE CustomerId = C.Id
        AND ProductName = 'Bread'
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...