Как исключить больше строк одним совпадением

#mysql #sql

#mysql #sql

Вопрос:

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

У меня есть следующая таблица:

 CREATE TABLE IF NOT EXISTS `Test` (
  `Id` INT NOT NULL AUTO_INCREMENT,
  `Name` VARCHAR(5) NOT NULL,
  `v1` INT NOT NULL,
  PRIMARY KEY (`Id`)
);

INSERT INTO `Test` (`Name`, `v1`) 
  VALUES ('A', 4), ('A', 3), ('B', 6), ('C', 1), ('C', 2), 
         ('C', 7), ('D', 7), ('D', 5), ('E', 3), ('F', 1), 
         ('F', 2), ('G', 7), ('H', 9), ('H', 1), ('I', 5);
  

Что мне нужно, так это найти все имена, которые соответствуют, например, 7.
Это 'C' , 'D' и 'G' .

И теперь мне нужно выбрать все строки, кроме 'C' , 'D' и 'G' .
Результирующая таблица должна быть:

 ===============
| Name  | v1  |
|–––––––––––––|
|   A   |  4  |
|   A   |  3  |
|   B   |  6  |
|   E   |  3  |
|   F   |  1  |
|   F   |  2  |
|   H   |  9  |
|   H   |  1  |
|   I   |  5  |
|–––––––––––––|
  

Я пробовал запрос:

 select t1.Name, t1.v1
from `Test` as t1
join (
  select Name from `Test`
  where v1 = 7
  ) as t2
  on t1.Name != t2.Name
  

но только понял, что я все еще не понимаю механику JOIN операторов.

Надеюсь на некоторую помощь в решении этой проблемы.
Заранее спасибо.

Ответ №1:

Этот запрос:

 SELECT Name FROM Test WHERE v1 = 7
  

возвращает все Name s, которые вы хотите исключить.
Используйте его с оператором NOT IN :

 SELECT * 
FROM Test
WHERE Name NOT IN (SELECT Name FROM Test WHERE v1 = 7)
  

Смотрите демонстрацию.
Результаты:

 > Id | Name | v1
> -: | :--- | -:
>  1 | A    |  4
>  2 | A    |  3
>  3 | B    |  6
>  9 | E    |  3
> 10 | F    |  1
> 11 | F    |  2
> 13 | H    |  9
> 14 | H    |  1
> 15 | I    |  5
  

Ответ №2:

Вы можете использовать not exists :

 select t.*
from test t
where not exists (select 1
                  from test t2
                  where t2.name = t.name and t2.v1 = 7
                 );
  

Это выбирает все строки, в test которых имя в строке не имеет строки с 7 , в любом месте таблицы.

Ответ №3:

Вот как это сделать с помощью объединений…

 SELECT x.* 
  FROM test x 
  LEFT 
  JOIN test y 
    ON y.name = x.name 
   AND y.v1 = 7 
 WHERE y.id IS NULL;
 ---- ------ ---- 
| Id | Name | v1 |
 ---- ------ ---- 
|  1 | A    |  4 |
|  2 | A    |  3 |
|  3 | B    |  6 |
|  9 | E    |  3 |
| 10 | F    |  1 |
| 11 | F    |  2 |
| 13 | H    |  9 |
| 14 | H    |  1 |
| 15 | I    |  5 |
 ---- ------ ----