sql >> データベース >  >> RDS >> Oracle

ソートを使用した再帰的サブクエリ

    最初は、一時テーブルを作成するよりも洗練されたソリューションを見つけることができませんでした。

    私は、SQLOracleの厄介な方言が何であるかを考えていました:

    1. IF TABLE EXISTS DELETE TABLEがないのはなぜですか?
    2. 文字列を使用してEXECUTEIMMEDIATEを実行する必要があるのはなぜですか? DROP TABLE TEMPを単独で実行できないのはなぜですか?
    3. ANCHORに括弧を入れずにORDERBYを使用できないのはなぜですか?
    4. UNIONALLの後に再帰SELECTでORDERBYを使用できないのはなぜですか?
    5. SQLWITHは標準化する必要があります。他のデータベースダイアレクトでは、WITHステートメントで列名を括弧で囲む必要はありません。そうしないと、UNION ALLの後の再帰的結合の時点で、意味のないALIASエラーが発生します。
    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 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
    



    1. SQLclを使用する場合、Oracleクエリ結果をHTMLファイルにエクスポートする

    2. MySQL COS()関数–MySQLの数値の正弦を返します

    3. MySQLでタイムスタンプを丸める方法

    4. Selectステートメントのケース