sql >> Databáze >  >> RDS >> Oracle

Rekurzivní subdotazování s řazením

Zpočátku jsem neviděl elegantnější řešení než vytvoření dočasné tabulky.

Přemýšlel jsem, jaký je to trapný dialekt SQL Oracle:

  1. Proč ne, POKUD EXISTUJE TABULKA, DELETE TABULKU?
  2. Proč musím provést EXECUTE IMMEDIATE pomocí řetězce? Proč nemohu jednoduše provést DROP TABLE TEMP samostatně?
  3. Proč nemohu mít ORDER BY bez vnoření v závorkách na ANCHOR?
  4. Proč nemohu mít ORDER BY na rekurzivním SELECT po UNION ALL?
  5. SQL S potřebuje standardizaci. Jiné dialekty databáze nevyžadují, aby byly názvy sloupců v závorkách v příkazu WITH. Pokud to neuděláte, dostanete nějakou nesmyslnou chybu ALIAS v bodě rekurzivního spojení po UNION ALL.
  6. Paginace:viz zde Bez LIMITU / 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;

Pak mě (mathguy na fóru Oracle Community Forum) upozornil, že moje HLOUBKA HLEDÁNÍ FIRST měla být právě od JOBMST_NAME.

Pak to všechno zapadne na své místo:

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



  1. Příkaz SQL SELECT INTO

  2. MySQL LIKE IN()?

  3. Index založený na SQLite Expression

  4. Kdy můžeme v PostgreSQL použít číslo identifikátoru místo jeho názvu?