最初は、一時テーブルを作成するよりも洗練されたソリューションを見つけることができませんでした。
私は、SQLOracleの厄介な方言が何であるかを考えていました:
- IF TABLE EXISTS DELETE TABLEがないのはなぜですか?
- 文字列を使用してEXECUTEIMMEDIATEを実行する必要があるのはなぜですか? DROP TABLE TEMPを単独で実行できないのはなぜですか?
- ANCHORに括弧を入れずにORDERBYを使用できないのはなぜですか?
- UNIONALLの後に再帰SELECTでORDERBYを使用できないのはなぜですか?
- SQLWITHは標準化する必要があります。他のデータベースダイアレクトでは、WITHステートメントで列名を括弧で囲む必要はありません。そうしないと、UNION ALLの後の再帰的結合の時点で、意味のないALIASエラーが発生します。
- ページネーション:ここを参照してください制限/オフセットなし
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 Community Forumのmathguy)は、私のSEARCHDEPTHFIRSTは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