2014-12-24 2 views
1

я одна таблицы customer_products с есть отображение клиента к продукции он используетMySQL отрицания из нескольких заходов

customer_id product_id 
c1   p1 
c1   p2 
c1   p3 
c2   p1 
c2   p2 
c3   p1 

Я хочу, чтобы все клиент, которые используют p2, но не p3. Можно ли достичь этого без использования вложенных запросов?

Я смог решить проблему с объединением вложенных запросов. Но поскольку вложенные соединения слишком медленные, я не могу получить желаемую производительность.

ответ

1

запроса с использованием условной агрегации в имеющем пункт для выбора всех клиентов, которые приобрели PRODUCT_ID p2, по крайней мере один раз и никогда не закупленные product_id p3

select customer_id 
from mytable 
where product_id in ('p2','p3') 
group by customer_id 
having count(case when product_id = 'p2' then 1 end) > 0 
and count(case when product_id = 'p3' then 1 end) = 0 
2

Да, это возможно, используя шаблон против объединения. Это левое соединение, чтобы вернуть всех клиентов, используя p2, вместе с соответствующими строками (то же самое customer_id), но используя p3, а затем отфильтровываем все строки, которые имели совпадение, с предикатом в предложении WHERE.

Например:

SELECT cp2.customer_id 
    FROM customer_products cp2 
    LEFT 
    JOIN customer_products cp3 
    ON cp3.customer_id = cp2.customer_id 
    AND cp3.product_id = 'p3' 
WHERE cp2.product_id = 'p2' 
    AND cp3.product_id IS NULL 

добавить DISTINCT ключевое слово пункт GROUP BY cp2.customer_id для устранения дубликатов (если (customer_id,product_id) не гарантировано быть уникальным.)

Соответствующие индексы улучшит производительность для больших наборов.

Смежные вопросы