Кто-нибудь может помочь в этом вопросе, пожалуйста, о том, как получить вывод, который я хочу?

Я ищу клиента, у которого есть тег "Kane", но не "Andrew".

Я ожидаю выхода:

«клиент 3» только потому, что на «клиенте 1» есть тег Andrew

INSERT INTO `client` (`id`, `name`) VALUES
  ('1', 'Client 1'),
  ('2', 'Client 2'),
  ('3', 'Client 3'),
  ('4', 'Client 4');

 INSERT INTO `tag` (`id`, `client_id`, `tag`) VALUES
  ('1', '1', 'Kane'),
  ('2', '1', 'Andrew'),
  ('3', '2', 'Andrew'),
  ('4', '3', 'Kane'),
  ('5', '3', 'James'),
  ('6', '4', 'Andrew');

## mysql query
select * from client where 
exists (
select client_id 
    from tag 
    where tag.client_id = client.id 
    and tag in ('Kane')
    and tag not in ( 'Andrew' )
)

http://sqlfiddle.com/#!9/48955/12

-1
tonoslfx 31 Авг 2017 в 18:37

6 ответов

Лучший ответ

Возможно, не самый эффективный способ, но это сработает:

select * from client where 
exists (
select client_id 
    from tag 
    where tag.client_id = client.id 
    and tag in ('Kane')
)
and not exists (
select client_id 
    from tag 
    where tag.client_id = client.id 
    and tag in ('Andrew')
)

Проблема с вашим запросом заключалась в том, что он пытался применить оба tag in ('Kane') и tag not in ( 'Andrew' ) в каждую строку одновременно. Поскольку первый пункт является ограничительным, второй пункт стал избыточным. Вы должны задать два вопроса отдельно.

1
ADyson 31 Авг 2017 в 15:42

Вот один из способов, с NOT IN():

SELECT *
FROM Client C
JOIN tag t on C.id = t.client_id
WHERE tag = 'Kane'
AND c.id NOT IN (SELECT client_id FROM tag WHERE tag = 'Andrew')

скрипка

По сути, вы получаете всех клиентов с tag = 'Kane', а затем удаляете тех, у кого есть экземпляр tag = 'Andrew', используя NOT IN()

3
Aaron Dietz 31 Авг 2017 в 15:45

< Сильный > Query

SELECT 
   client.id
 , client.name
FROM 
 CLIENT 
INNER JOIN 
 tag
ON
 client.id = tag.client_id 
GROUP BY 
   client.id
 , client.name
HAVING 
   SUM(tag = 'Kane')
 AND
   NOT SUM(tag = 'Andrew') 

< Сильный > Результат

    id  name      
------  ----------
     3  Client 3
2
Raymond Nijland 31 Авг 2017 в 15:43

Этот запрос должен работать для вашей ситуации.

 select * from client a
join tag b on a.id = b.client_id
where b.tag = 'Kane'
and not exists
(select * from tag c where c.client_id = b.client_id and tag = 'Andrew' )

Когда у вас есть 2 конфликтующих фильтра в соединении, второй фильтр объединяется с первым фильтром и конфликтами.

Решение заключается в том, существует или не существует для второго фильтра, таким образом, второе условие применяется к результатам запроса и рассматривается как отдельное условие.

0
isaace 1 Сен 2017 в 14:05

Вот метод грубой силы:

SELECT name
FROM client
WHERE id
IN
(SELECT client_id
 FROM tag
 WHERE tag = 'Kane') 
AND id NOT IN
(SELECT client_id
 FROM tag
 WHERE tag = 'Andrew') 
1
kjmerf 31 Авг 2017 в 15:50

Это может быть самый быстрый вариант.

SELECT c.id, c.name
FROM client AS c
INNER JOIN tag AS t1 ON a.id = t.client_id
LEFT JOIN tag AS t2 ON a.id = t2.client_id AND t2.tag = 'Andrew'
WHERE t1.tag = 'Kane'
AND t2.tag IS NULL
;
1
Uueerdo 31 Авг 2017 в 16:19