Как ВЫБРАТЬ противоположный (или что НЕ ВХОДИТ) набор результатов? - PullRequest
0 голосов
/ 07 мая 2018

У меня следующий запрос MySQL:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 
WHERE keyword IN ('red') 
GROUP BY k.gc_id 
HAVING COUNT(DISTINCT k.keyword) = 1

Возвращает мне список уникальных id, к которым прикреплен keyword «красный».

Я пытаюсь получить список уникальных id, которые не имеют keyword 'красный', прикрепленный к нему. В основном противоположность тому, что делает запрос.

Я пробовал этот запрос, используя NOT IN, но он возвращает все результаты, включая те, которые имеют «красный», связанный с ними. Как правильно это сделать?

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 
WHERE keyword NOT IN ('red') 
GROUP BY k.gc_id 

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

Один из вариантов - использовать условное агрегирование и утверждать, что red никогда не происходит:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM d_gift_card dgc
INNER JOIN
(
    SELECT gc_id
    FROM keyword
    GROUP BY gc_id
    HAVING SUM(CASE WHEN keyword = 'red' THEN 1 ELSE 0 END) = 0
) k
    ON k.gc_id = dgc.id;

Логическая проблема с проверкой ключевого слова в предложении WHERE заключается в том, что он применяется к отдельным записям, а не ко всем группам идентификаторов. Таким образом, он оставил бы несоответствующие записи, даже если у всей группы также были положительные совпадения.

0 голосов
/ 07 мая 2018

Я бы просто сделал это, переместив условие в предложение having:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k JOIN
     d_gift_card dgc
     ON k.gc_id = dgc.id 
GROUP BY dgc.name, dgc.id, dgc.has_special  
HAVING SUM( keyword IN ('red') ) = 0;

Обратите внимание, что предложение GROUP BY соответствует неагрегированным столбцам SELECT. Это лучшая практика, и в большинстве случаев она требуется стандартом SQL.

Выражение в предложении HAVING подсчитывает количество строк, равное 'red'. = 0 говорит, что их нет.

Наиболее эффективный способ написания запроса:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM d_gift_card dgc
WHERE NOT EXISTS (SELECT 1
                  FROM keyword k         
                  WHERE k.gc_id = dgc.id AND k.keyword IN ('red')
                 );

Это может использовать индекс на keyword(gc_id, keyword) и не требует агрегирования вообще.

0 голосов
/ 07 мая 2018

Вы можете использовать MINUS. Как то так:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 

MINUS

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 
WHERE keyword NOT IN ('red') 
GROUP BY k.gc_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...