Oracle
 sql >> база данни >  >> RDS >> Oracle

Преобразуване на NOT IN в NOT EXISTS

Доста е просто, когато хванете цаката:

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id           -- take this line
        FROM ENROLLMENT e
        WHERE e.Mark < 70);

Този ред основно сравнява S.S_Id с всички e.S_Id стойности, които идват от подзаявката.

Сега променете това на NOT EXISTS и поставете проверка за равенство S.S_Id = e.S_Id , вътре в подзаявката:

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT e.S_Id          
        FROM ENROLLMENT e
        WHERE (e.Mark < 70)       -- if this is complex, you'll need parentheses
        AND S.S_Id = e.S_Id);

Малка възможна промяна е да осъзнаете, че (SELECT e.S_Id ... всъщност не се нуждае от e.S_Id . Подзаявки с EXISTS и NOT EXISTS просто проверете дали има върнати редове или не и стойностите на колоните нямат значение. Можете да поставите SELECT * или константа там (SELECT 1 е често срещано) или SELECT NULL или дори SELECT 1/0 (Да, това ще свърши работа!):

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT 1
        FROM ENROLLMENT e
        WHERE e.Mark < 70  
        AND S.S_Id = e.S_Id);

Друго важно съображение е, че когато извършвате преобразуването по този начин, (привидно еквивалентно) NOT EXISTS и NOT IN писанията на заявка са наистина еквивалентни само ако и двата S_Id колоните не могат да се нулират. Ако e.S_Id колоната е nullable, NOT IN може да доведе до това, че цялата заявка не връща никакви редове (защото x NOT IN (a, b, c, ...) е еквивалентен на x<>a AND x<>b AND ... и това условие не може да бъде вярно, когато едно от a,b,c... е NULL .)

По подобни причини ще имате различни резултати, ако s.S_Id е nullable (това не е много вероятно в този случай, тъй като вероятно е първичният ключ, но в други случаи има значение.)

Така че почти винаги е по-добре да използвате NOT EXISTS , тъй като се държи различно дори ако някоя от колоните е nullable (S.S_Id = e.S_Id check ще отхвърли редове с null по-рано) и обикновено това поведение е желаното. Във въпроса има много подробности: НЕ В срещу НЕ СЪЩЕСТВУВА , в отговора на @Martin Smith. Там също ще намерите начини за конвертиране на NOT IN на NOT EXISTS и запазете нулевото (неприятно) поведение.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle SQL Часове Разлика между датите в ЧЧ:ММ:СС

  2. Използване на функцията Max() за избор на групови стойности

  3. Как да получите втори по големина или трети по големина запис от таблица

  4. SQL заявка за разрешаване на транзитивни зависимости в базата данни

  5. Python Oracle, грешка при вмъкване на None