Фильтрация таблицы по значениям другой таблицы

#sql #db2

#sql #db2

Вопрос:

У меня есть 2 таблицы:

Значение

  ---- ------- 
| id | name  |
 ---- ------- 
|  1 | Peter |
|  2 | Jane  |
|  3 | Joe   |
 ---- ------- 
  

Фильтр

  ---- --------- ------ 
| id | valueid | type |
 ---- --------- ------ 
|  1 |       1 | A    |
|  2 |       1 | B    |
|  3 |       1 | C    |
|  4 |       1 | D    |
|  5 |       2 | A    |
|  6 |       2 | C    |
|  7 |       2 | E    |
|  8 |       3 | A    |
|  9 |       3 | D    |
 ---- --------- ------ 
  

Мне нужно получить значения из таблицы значений, где связанная таблица фильтров не содержит тип ‘B’ или ‘C’
Итак, в этом кратком примере это будет только Joe.

Пожалуйста, обратите внимание, что это DB2 DB, и у меня ограниченные разрешения только для запуска selects.

Ответ №1:

Или также NOT IN (<*fullselect*) предикат: только то, что мой результат — «Джо», а не «Джейн», и на это будет указывать совокупность данных …

 WITH
-- your input, sans reserved words
val(id,nam) AS (
          SELECT 1,'Peter' FROM sysibm.sysdummy1
UNION ALL SELECT 2,'Jane'  FROM sysibm.sysdummy1
UNION ALL SELECT 3,'Joe'   FROM sysibm.sysdummy1
)
,
filtr(id,valueid,typ) AS (
          SELECT 1,1,'A' FROM sysibm.sysdummy1
UNION ALL SELECT 2,1,'B' FROM sysibm.sysdummy1
UNION ALL SELECT 3,1,'C' FROM sysibm.sysdummy1
UNION ALL SELECT 4,1,'D' FROM sysibm.sysdummy1
UNION ALL SELECT 5,2,'A' FROM sysibm.sysdummy1
UNION ALL SELECT 6,2,'C' FROM sysibm.sysdummy1
UNION ALL SELECT 7,2,'E' FROM sysibm.sysdummy1
UNION ALL SELECT 8,3,'A' FROM sysibm.sysdummy1
UNION ALL SELECT 9,3,'D' FROM sysibm.sysdummy1
)
-- real query starts here
SELECT
  *
FROM val
WHERE id NOT IN (
  SELECT valueid FROM filtr WHERE typ IN ('B','C')
)
;
-- out  id |  nam  
-- out ---- -------
-- out   3 | Joe

  

Или также неудачное соединение слева:

 SELECT
  val.*
FROM val
LEFT JOIN (
  SELECT valueid FROM filtr WHERE typ IN ('B','C')
) filtr
ON filtr.valueid = val.id
WHERE valueid IS NULL
  

Комментарии:

1. ОП говорит «Джейн», вы говорите «Питер», а я говорю «Джо». ЛОЛ

2. Я ошибочно присоединился к over USING(id) вместо val.id <-> filtr.valueid .. В конце концов, это «Джо» — тем временем исправил мой…

3. Хорошо 1. Предостережение: я обычно избегаю NOT IN , поскольку это не работает при наличии нулей.

4. Да, это была моя ошибка, я на самом деле ищу Джо здесь.

5. … и третий способ, только что добавленный к моему ответу, с использованием неудачного соединения слева. Я не знаю о DB2 так хорошо, как раньше, но, в зависимости от СУБД, один из 3 способов сделать это лучше, чем два других. Стоит изучить …

Ответ №2:

Вы можете использовать EXISTS , как в:

 select *
from value v
where not exists (
  select null from filter f
  where f.valueid = v.id and f.type in ('B', 'C')
);
  

Результат:

  ID  NAME 
 --- -----
 3   Joe  
  

Смотрите Пример выполнения в db<>fiddle.