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

Rekursive Unterabfrage mit Sortierung

Anfangs sah ich keine elegantere Lösung, als eine temporäre Tabelle zu erstellen.

Ich dachte, was für ein umständlicher Dialekt von SQL Oracle ist:

  1. Warum keine IF TABLE EXISTS DELETE TABLE?
  2. Warum muss ich EXECUTE IMMEDIATE mit einem String machen? Warum kann ich DROP TABLE TEMP nicht alleine machen?
  3. Warum kann ich ORDER BY nicht haben, ohne in Klammern auf ANCHOR zu verschachteln?
  4. Warum kann ich ORDER BY nicht bei rekursivem SELECT nach UNION ALL haben?
  5. SQL WITH muss standardisiert werden. Andere Datenbankdialekte erfordern es nicht, dass Spaltennamen in der WITH-Anweisung eingeklammert werden. Wenn Sie das nicht tun, erhalten Sie einen bedeutungslosen ALIAS-Fehler an der Stelle des rekursiven Joins nach UNION ALL.
  6. Paginierung:Siehe hier No LIMIT / OFFSET
DECLARE
 v_c NUMBER;
BEGIN
SELECT COUNT(*) INTO v_c FROM user_tables WHERE TABLE_NAME = 'TEMP';
IF v_c = 1 THEN
  EXECUTE IMMEDIATE 'DROP TABLE TEMP';
END IF;
END;
CREATE TABLE TEMP AS  (
    SELECT * FROM (
      SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE
      FROM TIDAL.JOBMST
      WHERE JOBMST_PRNTID IS NOT NULL
      ORDER BY JOBMST_PRNTID, JOBMST_NAME
    )
);
WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL) AS  (
  SELECT * FROM (
    SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1
    FROM TIDAL.JOBMST
    WHERE JOBMST_PRNTID IS NULL
    ORDER BY JOBMST_NAME
  )
UNION ALL
SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1
FROM TEMP J2
INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID
WHERE J2.JOBMST_PRNTID IS NOT NULL
)
SEARCH DEPTH FIRST BY JOBMST_ID SET DISP_SEQ
SELECT *
FROM J1
ORDER BY DISP_SEQ;

Dann (Mathguy im Oracle Community Forum) wies mich darauf hin, dass meine SEARCH DEPTH FIRST nur von JOBMST_NAME hätte sein sollen.

Dann fügt sich alles zusammen:

WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL) AS  (
    SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1
    FROM TIDAL.JOBMST
    WHERE JOBMST_PRNTID IS NULL
UNION ALL
SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1
FROM TIDAL.JOBMST J2
INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID
WHERE J2.JOBMST_PRNTID IS NOT NULL
)
SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ
SELECT *
FROM J1
ORDER BY DISP_SEQ