Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
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] Ответить | Цитировать Сообщить модератору |
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] Ответить | Цитировать Сообщить модератору |
aleks222
Guest |
Лехко. 1. Обучиться пользоваться кляузой exists. 2. Осознать, что "купил товар только из группы" = "не купил товар НЕ ПРИНАДЛЕЖАЩЕЙ группе" |
||
3 авг 17, 16:19 [20698518] Ответить | Цитировать Сообщить модератору |
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] Ответить | Цитировать Сообщить модератору |
aleks222
Guest |
GROUP BY - не нужен. Кроме exists есть еще NOT exists. |
3 авг 17, 16:43 [20698591] Ответить | Цитировать Сообщить модератору |
Азагаш Member Откуда: Сообщений: 450 |
а not не загонит план выполнения в говнище? |
||
3 авг 17, 16:54 [20698629] Ответить | Цитировать Сообщить модератору |
aleks222
Guest |
Проблемы не в |
||||
3 авг 17, 17:00 [20698656] Ответить | Цитировать Сообщить модератору |
Dmitry V. Liseev Member [заблокирован] Откуда: Санкт-Петербург Сообщений: 5489 |
Предлагаю поджоинить (по умолчанию 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] Ответить | Цитировать Сообщить модератору |
hulk77 Member Откуда: Сообщений: 123 |
SQL говорит что нужен.. "CONTACT_ID" недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY. |
||
3 авг 17, 19:19 [20698996] Ответить | Цитировать Сообщить модератору |
hulk77 Member Откуда: Сообщений: 123 |
У меня этот вариант не сработал, к сожалению Адаптировал ваш код 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] Ответить | Цитировать Сообщить модератору |
hulk77 Member Откуда: Сообщений: 123 |
aleks222, Dmitry V. Liseev Спасибо за помощь в решении задачи |
3 авг 17, 19:24 [20699008] Ответить | Цитировать Сообщить модератору |
Бен-Ган
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] Ответить | Цитировать Сообщить модератору |
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 | ![]() |