sql >> Base de Datos >  >> RDS >> Oracle

Subconsulta recursiva con clasificación

Inicialmente, no pude ver una solución más elegante que crear una tabla temporal.

Estaba pensando, qué dialecto incómodo de SQL Oracle es:

  1. ¿Por qué no IF TABLE EXISTE DELE TABLE?
  2. ¿Por qué tengo que ejecutar EJECUTAR INMEDIATAMENTE con una cadena? ¿Por qué no puedo hacer DROP TABLE TEMP solo?
  3. ¿Por qué no puedo tener ORDER BY sin anidar entre paréntesis en ANCHOR?
  4. ¿Por qué no puedo tener ORDER BY en SELECT recursivo después de UNION ALL?
  5. SQL WITH necesita estandarizarse. Otros dialectos de la base de datos no requieren que los nombres de las columnas estén entre paréntesis en la instrucción WITH. Si no lo hace, obtendrá un error ALIAS sin sentido, en el punto de la unión recursiva después de UNION ALL.
  6. Paginación:Ver aquí Sin LÍMITE / DESPLAZAMIENTO
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;

Luego (mathguy en Oracle Community Forum) me señaló que mi PROFUNDIDAD DE BÚSQUEDA PRIMERO debería haber sido por JOBMST_NAME.

Entonces todo encaja:

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