Исключить строки на основе других строк (SQL) - PullRequest
3 голосов
/ 28 января 2011

Скажите, что у меня есть такой запрос:

SELECT *
FROM TABLE

И он возвращает это:

TABLE
ID | DATA | VAL
===============
01 | ABCD | 1
01 | DEFG | 2
02 | FGHI | 3
02 | HIJK | 2
03 | JKLM | 3
03 | LMNO | 4
04 | NOPQ | 0
04 | PQRS | 1

В настоящее время у меня есть запрос, который пытается найти только хорошие значения, подобные этому, но он некорректен, потому что включены идентификаторы с плохими VAL в других строках, а это не то, что я хотел бы.

SELECT *
FROM TABLE
WHERE TABLE.VAL IN ("1","2","3")

вернет это (при отсутствии LMNO и PQRS):

TABLE
ID | DATA | VAL
===============
01 | ABCD | 1
01 | DEFG | 2
02 | FGHI | 3
02 | HIJK | 2
03 | JKLM | 3
04 | NOPQ | 0

Однако мне нужны только строки, в которых идентификатор не имеет неверных значений. Итак, 01 и 02 в порядке, потому что все их строки имеют хорошие результаты. 03 и 04 плохие, потому что они испорчены плохими результатами в других строках.

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

Лучшее, что я мог придумать, это:

SELECT *
FROM TABLE
WHERE COUNT( SELECT ID
             FROM TABLE
             WHERE TABLE.VAL NOT IN ("1","2","3")
           ) = 0

Это жизнеспособно? Есть ли лучшая альтернатива?

Спасибо!

Ответы [ 4 ]

5 голосов
/ 28 января 2011

Использование:

SELECT * 
  FROM TABLE a
 WHERE a.val IN (1,2,3)
   AND NOT EXISTS(SELECT NULL
                    FROM TABLE b
                   WHERE b.id = a.id
                     AND b.val NOT IN (1, 2, 3))
1 голос
/ 28 января 2011

Вот еще одна альтернатива, которая будет проходить через TBL один раз, агрегировать и, используя найденные идентификаторы, извлекать данные из TBL

SELECT *
WHERE ID IN
(
    SELECT
       ID,
       CASE WHEN val in (1,2,3) THEN 1 ELSE 0 END Test
    FROM TBL
    GROUP BY ID
    HAVING MIN(val) = 1
)

Для ключей с несколькими столбцами и в качестве альтернативы вышеуказанному INФорма, вы можете использовать форму JOIN.

SELECT T.*
FROM (
    SELECT
       Company, OrderNumber,
       CASE WHEN val in (1,2,3) THEN 1 ELSE 0 END Test
    FROM TBL
    GROUP BY Company, OrderNumber
    HAVING MIN(val) = 1
    ) KEEP
INNER JOIN TBL T ON T.Company = KEEP.Company and T.OrderNumber=KEEP.OrderNumber
1 голос
/ 28 января 2011

вы можете попробовать что-то вроде

SELECT *
FROM TABLE
WHERE TABLE.ID NOT IN(
    SELECT ID
    FROM TABLE
    WHERE TABLE.VAL < '1'
    OR TABLE.VAL > '3'
)
1 голос
/ 28 января 2011

вы можете использовать оператор минус.

псевдопрос

select everything
from tables
where id in ( select id from table minus select id from table where val is bad )
...