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