web-dev-qa-db-ja.com

Oracleエラー「値が多すぎます」は、ネストされたSELECTで解決する必要があります

複雑なネストされたSELECTを処理しているときに、Oracleで「値が多すぎます」エラーが発生しました。

会社の階層を説明するおもちゃの問題に関する、私の問題の簡単な説明。 2つのテーブルがあります。

  • ACG_EMPLOYEES、すべての従業員をリストします

enter image description here

  • ACG_BOSS_OF、これは単に誰をリストするか(b_id)は誰のボスか(e_id

enter image description here

できます

SELECT b_id as boss,
             LTRIM(MAX(SYS_CONNECT_BY_PATH(e_id,','))
             KEEP (DENSE_RANK LAST ORDER BY curr),',') as minion
FROM (SELECT b_id,
             e_id,
             ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY e_id) AS curr,
             ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY e_id) -1 AS prev
      FROM acg_boss_of)
GROUP BY b_id
CONNECT BY prev = PRIOR curr AND b_id = PRIOR b_id
START WITH curr = 1

階層のリーフではないすべての従業員の「ミニオン」のリストを取得するには: enter image description here

しかし、ACG_EMPLOYEESテーブルから他のフィールドも取得したいとします。この場合、各ボスに対してnameを使用します。

enter image description here

私が試してみました

SELECT 
emp.name, 
(SELECT b_id as boss,
             LTRIM(MAX(SYS_CONNECT_BY_PATH(e_id,','))
             KEEP (DENSE_RANK LAST ORDER BY curr),',') as minion
FROM (SELECT b_id,
             e_id,
             ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY e_id) AS curr,
             ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY e_id) -1 AS prev
      FROM acg_boss_of)
GROUP BY b_id
CONNECT BY prev = PRIOR curr AND b_id = PRIOR b_id
START WITH curr = 1) minion
FROM acg_employees emp

しかし、先ほど述べた「値が多すぎます」というエラーが表示されます。

この種の問題を解決するためのいくつかの提案を見てきました。ただし、このステートメントはProduct Lifecycle Managementアプリで使用されるため、どのステートメントを使用することもできません。このステートメントは、どれほど複雑であっても(単一のSELECTとして定義する必要があります)(OK、JOINも使用できますが、ストアドプロシージャは使用できません)など)。

2
user14788

結合を使用しますか?

SELECT 
  minion.boss,
  emp.name, 
  minion.minion
FROM acg_employees emp 
JOIN    
    (SELECT b_id as boss,
                 LTRIM(MAX(SYS_CONNECT_BY_PATH(e_id,','))
                 KEEP (DENSE_RANK LAST ORDER BY curr),',') as minion
    FROM (SELECT b_id,
                 e_id,
                 ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY e_id) AS curr,
                 ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY e_id) -1 AS prev
          FROM acg_boss_of)
    GROUP BY b_id
    CONNECT BY prev = PRIOR curr AND b_id = PRIOR b_id
    START WITH curr = 1) minion
ON (minion.boss=emp.e_id)
3
Florin Ghita