Oracle
 sql >> Datenbank >  >> RDS >> Oracle

SELECT aus Tabelle mit Varying IN-Liste in WHERE-Klausel

Ihre Anforderung wird als Variierende IN-Listen bezeichnet . Siehe Varying IN-Werteliste in WHERE-Klausel

Grund : IN ('1, 2, 3') ist NICHT dasselbe wie IN (1, 2, 3) ODER IN('1', '2', '3')

Daher

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

ist gleich

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

was einen Fehler auslösen würde 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

NICHT dasselbe wie

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

was Ihnen eine korrekte Ausgabe geben würde -

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

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

Lösung:

Für Ihre Anforderung können Sie es so erreichen -

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

Alternativ können Sie Ihre eigene TABLE-Funktion erstellen oder eine Pipeline-Funktion um das zu erreichen. Ihr Ziel sollte es sein, die durch Kommas getrennte IN-Liste in mehrere Zeilen aufzuteilen . Wie Sie es tun, liegt ganz bei Ihnen!

Arbeitsdemo

Nehmen wir ein Beispiel für den Standard EMP Tabelle in SCOTT Schema.

Ich habe eine Liste mit Jobs in einer Zeichenfolge und möchte die Mitarbeiter für diese Jobs zählen:

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! Was ist passiert? Die standardmäßige emp-Tabelle sollte eine Ausgabe 10 liefern. Der Grund dafür ist, dass die variierende IN-Liste .

Sehen wir uns den richtigen Weg an:

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.