Oracle
 sql >> база данни >  >> RDS >> Oracle

Рекурсивна подзаявка със сортиране

Първоначално не можах да видя по-елегантно решение от създаването на временна таблица.

Мислех си какъв неудобен диалект на SQL Oracle е:

  1. Защо не АКО СЪЩЕСТВУВА ТАБЛИЦА, ИЗТРИВАТЕ ТАБЛИЦАТА?
  2. Защо трябва да правя ИЗПЪЛНЯВАНЕ НЕЗАБАВНО с низ? Защо не мога просто да направя DROP TABLE TEMP самостоятелно?
  3. Защо не мога да имам ORDER BY без вмъкване в скоби на ANCHOR?
  4. Защо не мога да имам ORDER BY при рекурсивно SELECT след UNION ALL?
  5. SQL WITH се нуждае от стандартизиране. Други диалекти на базата данни не изискват имената на колони да бъдат поставени в скоби в израза WITH. Ако не го направите, ще получите някаква безсмислена грешка ALIAS в точката на рекурсивното присъединяване след UNION ALL.
  6. Пагинация:Вижте тук Без ОГРАНИЧЕНИЕ/ОТМЕСТВАНЕ
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;

Тогава (математик във форума на общността на Oracle) ми посочи, че ПЪРВО ДЪЛБОЧИНАТА НА ТЪРСЕНЕТО трябва да е току-що от JOBMST_NAME.

Тогава всичко си идва на мястото:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Функция CURRENT_DATE в Oracle

  2. Преобразуване на текуща_времева марка на Oracle в секунди

  3. Как да форматирате месеца с римски цифри в Oracle

  4. LEAD и LAG аналитични функции

  5. Как да запишете BLOB като файл в PL/SQL?