Oracle
 sql >> Baza danych >  >> RDS >> Oracle

SELECT z tabeli z listą Varying IN w klauzuli WHERE

Twoje wymaganie nazywa się Varying IN-lists . Zobacz Listę zmiennych IN w klauzuli WHERE

Powód: IN ('1, 2, 3') jest NIE to samo co IN (1, 2, 3) OR IN('1', '2', '3')

Stąd

SELECT * FROM temp_id WHERE data_id IN(SELECT id FROM temp);

jest taki sam jak

SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');

co spowodowałoby błąd ORA-01722: invalid number -

SQL> SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');
SELECT * FROM temp_id WHERE data_id IN('1, 2, 3')
                                       *
ERROR at line 1:
ORA-01722: invalid number


SQL> SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp);
SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp)
                                              *
ERROR at line 1:
ORA-01722: invalid number

NIE to samo, co

SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

co dałoby poprawny wynik -

SQL> SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

   DATA_ID
----------
         1
         2
         3

Rozwiązanie:

Dla swoich wymagań możesz to osiągnąć w ten sposób -

SQL> SELECT * FROM temp;

IDS
--------------------------------------------------------------
1, 2, 3

SQL> SELECT * FROM temp_id;

   DATA_ID
----------
         1
         2
         3
         4
         5

SQL> WITH data AS
  2    (SELECT to_number(trim(regexp_substr(ids, '[^,]+', 1, LEVEL))) ids
  3    FROM temp
  4      CONNECT BY instr(ids, ',', 1, LEVEL - 1) > 0
  5    )
  6  SELECT * FROM temp_id WHERE data_id IN
  7    (SELECT ids FROM data
  8    )
  9  /

   DATA_ID
----------
         1
         2
         3

Alternatywnie możesz utworzyć własną funkcję TABLE lub funkcja potokowa osiągnąć to. Twoim celem powinno być podzielenie listy IN rozdzielonych przecinkami na wiele wierszy . Jak to zrobisz, zależy od Ciebie!

Praca demonstracyjna

Weźmy przykład standardowego EMP tabela w SCOTT schemat.

Mam listę zadań w ciągu i chcę policzyć pracowników do tych zadań:

SQL> SET serveroutput ON
SQL> DECLARE
  2    str VARCHAR2(100);
  3    cnt NUMBER;
  4  BEGIN
  5    str := q'[CLERK,SALESMAN,ANALYST]';
  6    SELECT COUNT(*) INTO cnt FROM emp WHERE JOB IN (str);
  7    dbms_output.put_line('The total count is '||cnt);
  8  END;
  9  /
The total count is 0

PL/SQL procedure successfully completed.

Oh! Co się stało? Standardowa tabela emp powinna dać wynik 10. Powodem jest to, że lista zmiennych IN .

Zobaczmy właściwy sposób:

SQL> SET serveroutput ON
SQL> DECLARE
  2    str VARCHAR2(100);
  3    cnt NUMBER;
  4  BEGIN
  5    str := q'[CLERK,SALESMAN,ANALYST]';
  6    SELECT COUNT(*)
  7    INTO cnt
  8    FROM emp
  9    WHERE job IN
 10      (SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL))
 11      FROM dual
 12        CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
 13      );
 14    dbms_output.put_line('The total count is '||cnt);
 15  END;
 16  /
The total count is 10

PL/SQL procedure successfully completed.


  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 10g - optymalizuj GDZIE NIE JEST NULL

  2. Utwórz wyzwalacz, który aktualizuje kolumnę w jednej tabeli, gdy kolumna w innej tabeli jest aktualizowana

  3. Jak obliczyć różnicę między dwiema datami w PostgreSQL/Oracle?

  4. Jak zwrócić listę prawidłowych stref czasowych w bazie danych Oracle

  5. Anonimowy typ TABLE lub VARRAY w Oracle