複雑なネストされたSELECTを処理しているときに、Oracleで「値が多すぎます」エラーが発生しました。
会社の階層を説明するおもちゃの問題に関する、私の問題の簡単な説明。 2つのテーブルがあります。
できます
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
階層のリーフではないすべての従業員の「ミニオン」のリストを取得するには:
しかし、ACG_EMPLOYEESテーブルから他のフィールドも取得したいとします。この場合、各ボスに対してnameを使用します。
私が試してみました
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も使用できますが、ストアドプロシージャは使用できません)など)。
結合を使用しますか?
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)