Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Выгрузить клиентов, купивших только один указанный товар  [new]
hulk77
Member

Откуда:
Сообщений: 123
Добрый день
Помогите пож по запросу
Есть таблица счетов, в счете может быть несколько товаров.
Мне нужно выгрузить список тех клиентов, которые купили только определенную группу товаров (поле [Продукт])

Чтото такое кручу:
        SELECT i.[CONTACT_ID],COUNT(p.[Продукт])
	FROM [Счета] i 
	INNER JOIN [Продукты] p ON p.[PRODUCT_ID]=i.[PRODUCT_ID]
	WHERE i.[Сумма оплаты]>0
	GROUP BY i.[CONTACT_ID]
        HAVING COUNT(p.[Продукт]) = 1


Таким образом получаю тех кто купил только одну любую группу товаров
А как прикрутить условие отбора к таблице [Продукты] что нужна только [Группа]='Группа А' ?
3 авг 17, 15:50    [20698382]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
hulk77
Member

Откуда:
Сообщений: 123
Такой вот монстр получился

	    SELECT DISTINCT i.[CONTACT_ID]
		FROM [ZohoSO].[dbo].[Счета] i 
		INNER JOIN [ZohoSO].[dbo].[Продукты] p ON p.[PRODUCT_ID]=i.[PRODUCT_ID]

		INNER JOIN (
			   SELECT i.[CONTACT_ID]
				 FROM [ZohoSO].[dbo].[Счета] i 
				 INNER JOIN [ZohoSO].[dbo].[Продукты] p ON p.[PRODUCT_ID]=i.[PRODUCT_ID]
			   WHERE i.[Сумма оплаты]>0
			   GROUP BY i.[CONTACT_ID]
			   HAVING COUNT(p.[Продукт]) = 1
		   ) b ON b.[CONTACT_ID]=i.[CONTACT_ID]

		WHERE i.[Сумма оплаты]>0 AND p.[Продукт] = '...'


Можно как-то упростить код?

Сообщение было отредактировано: 3 авг 17, 16:43
3 авг 17, 16:01    [20698439]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
aleks222
Guest
hulk77
Можно как-то упростить код?

Лехко.
1. Обучиться пользоваться кляузой exists.
2. Осознать, что "купил товар только из группы" = "не купил товар НЕ ПРИНАДЛЕЖАЩЕЙ группе"
3 авг 17, 16:19    [20698518]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
hulk77
Member

Откуда:
Сообщений: 123
aleks222,

вы имели ввиду так?

	 	SELECT DISTINCT i.[CONTACT_ID]
		FROM [dbo].[Счета] i 
		INNER JOIN [dbo].[Продукты] p ON p.[PRODUCT_ID]=i.[PRODUCT_ID]

		WHERE i.[Сумма оплаты]>0 AND p.[Продукт] = '8'
		AND EXISTS (
			   SELECT ii.[CONTACT_ID]
				 FROM [dbo].[Счета] ii
				 INNER JOIN [dbo].[Продукты] pp ON pp.[PRODUCT_ID]=ii.[PRODUCT_ID]
			   WHERE ii.[Сумма оплаты]>0 AND i.[CONTACT_ID]=ii.[CONTACT_ID]
			   GROUP BY ii.[CONTACT_ID]
			   HAVING COUNT(pp.[Продукт]) = 1
		   )


результат совпал с результатом моего громоздкого запроса
3 авг 17, 16:37    [20698567]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
aleks222
Guest
GROUP BY - не нужен.

Кроме exists есть еще NOT exists.
3 авг 17, 16:43    [20698591]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
Азагаш
Member

Откуда:
Сообщений: 450
aleks222
GROUP BY - не нужен.

Кроме exists есть еще NOT exists.

а not не загонит план выполнения в говнище?
3 авг 17, 16:54    [20698629]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
aleks222
Guest
Азагаш
aleks222
GROUP BY - не нужен.

Кроме exists есть еще NOT exists.

а not не загонит план выполнения в говнище?


Проблемы не в сортирах not exists, проблемы в головах
3 авг 17, 17:00    [20698656]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5490
Предлагаю поджоинить (по умолчанию INNER JOIN) на продукты, которые являются интересующей нас группой, и на продукты, которые не являются такой группой (LEFT JOIN). И уже по условию выбрать те, которые не имеют ни одной посторонней группы:

FROM [Счета] i
JOIN [Продукты] grp ON grp.ProductId = i.ProductId AND grp.Product = 8
LEFT JOIN [Продукты] not_grp ON not_grp.ProductId = i.ProductId AND not_grp.Product <> 8
WHERE not_grp.ProductId IS NULL
3 авг 17, 17:52    [20698789]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
hulk77
Member

Откуда:
Сообщений: 123
aleks222
GROUP BY - не нужен.

SQL говорит что нужен..
"CONTACT_ID" недопустим в списке выбора, поскольку он не содержится ни в агрегатной  функции, ни в предложении GROUP BY.
3 авг 17, 19:19    [20698996]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
hulk77
Member

Откуда:
Сообщений: 123
Dmitry V. Liseev
Предлагаю поджоинить (по умолчанию INNER JOIN) на продукты, которые являются интересующей нас группой, и на продукты, которые не являются такой группой (LEFT JOIN). И уже по условию выбрать те, которые не имеют ни одной посторонней группы:

FROM [Счета] i
JOIN [Продукты] grp ON grp.ProductId = i.ProductId AND grp.Product = 8
LEFT JOIN [Продукты] not_grp ON not_grp.ProductId = i.ProductId AND not_grp.Product <> 8
WHERE not_grp.ProductId IS NULL



У меня этот вариант не сработал, к сожалению
Адаптировал ваш код
			SELECT DISTINCT i.[CONTACT_ID]
			FROM [dbo].[Счета] i 
			INNER JOIN [dbo].[Продукты] grp ON grp.[PRODUCT_ID]=i.[PRODUCT_ID] AND grp.[Продукт] = '8'
			LEFT JOIN [dbo].[Продукты] not_grp ON not_grp.[PRODUCT_ID]=i.[PRODUCT_ID] AND not_grp.[Продукт] <> '8'

			WHERE i.[Сумма оплаты]>0 AND not_grp.[PRODUCT_ID] IS NULL



Для перепроверки запустил такой запрос, предполагая что при верном результате он должен вернуть только группу 8

		SELECT DISTINCT p.[Продукт]
		FROM [dbo].[Счета] i 
		INNER JOIN [dbo].[Продукты] p ON p.[PRODUCT_ID]=i.[PRODUCT_ID]
		INNER JOIN (

			SELECT DISTINCT i.[CONTACT_ID]
			FROM [dbo].[Счета] i 
			INNER JOIN [dbo].[Продукты] grp ON grp.[PRODUCT_ID]=i.[PRODUCT_ID] AND grp.[Продукт] = '8'
			LEFT JOIN [dbo].[Продукты] not_grp ON not_grp.[PRODUCT_ID]=i.[PRODUCT_ID] AND not_grp.[Продукт] <> '8'

			WHERE i.[Сумма оплаты]>0 AND not_grp.[PRODUCT_ID] IS NULL

		) a on a.CONTACT_ID=i.CONTACT_ID
		WHERE i.[Сумма оплаты]>0


Но он вернул 20 значений групп
3 авг 17, 19:23    [20699005]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
hulk77
Member

Откуда:
Сообщений: 123
aleks222, Dmitry V. Liseev Спасибо за помощь в решении задачи
3 авг 17, 19:24    [20699008]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
Бен-Ган
Guest
BEGIN TRANSACTION;

CREATE TABLE dbo.Orders (
  CustomerID INT
 ,ProductID INT);

INSERT INTO dbo.Orders (CustomerID
                       ,ProductID)
VALUES (1, 1)
      ,(1, 2)
      ,(2, 1)
      ,(3, 1)
      ,(4, 2)
      ,(4, 5);

SELECT  CustomerID
FROM    dbo.Orders
WHERE   (ProductID = 1)
EXCEPT
SELECT  CustomerID
FROM    dbo.Orders
WHERE   (ProductID <> 1);

ROLLBACK;
3 авг 17, 23:07    [20699286]     Ответить | Цитировать Сообщить модератору
 Re: Выгрузить клиентов, купивших только один указанный товар  [new]
aleks222
Guest
Дело фкуса, но с exists не сильно длиннее

declare @Orders TABLE(
  CustomerID INT
 ,ProductID INT);

INSERT INTO @Orders (CustomerID, ProductID)
VALUES (1, 1)
      ,(1, 2)
      ,(2, 1)
      ,(2, 1)
      ,(3, 1)
      ,(4, 2)
      ,(4, 5);

SELECT  distinct CustomerID
FROM    @Orders as o
WHERE   (ProductID = 1)
     and not exists ( select * from @Orders where CustomerID = o.CustomerID and ProductID <> o.ProductID )
4 авг 17, 06:08    [20699429]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить