編集:サブクエリを使用しようとした理由を明確にするために、場所エンティティを導入して追加情報を提供しました
Oracle 11gデータベースには、最終的に数百万行を含む要素の階層構造テーブルがあります。各行には、その親を指すインデックス付きの外部キーがあり、循環は許可されていません。要素には名前と型もあります。それに加えて、要素に似た別のエンティティーlocationがあります(階層型で、親 + 名前を指す外部キーがあります)。最上位の要素(あなたのルート) は場所にあります(それらはLocationIdによって接続されています)。したがって、2 つのエンティティがあります。
位置:
- ID [NUMBER(9,0), PK]
- ParentId [NUMBER(9,0), FK]
- 名前 [VARCHAR2(200)]
エレメント:
- ID [NUMBER(9,0), PK]
- LocationId [NUMBER(9,0), FK]
- ParentId [NUMBER(9,0), FK]
- TypeId [NUMBER(9,0), FK]
- 名前 [VARCHAR2(200)]
たとえば、テーブルに次のデータが含まれているとします。
位置:
Id | ParentId | Name
----------------------------------
100 | null | TopLocation
101 | 100 | Level1Location
102 | 101 | Level2Location
エレメント:
Id | LocationId | ParentId | TypeId | Name
----------------------------------------------------
1 | 102 | null | 10 | TopParent
2 | null | 1 | 11 | Level1Child
3 | null | 2 | 11 | Level2Child
私がしなければならないのは、要素のクエリを作成することです。これは、基本的な 4 つの要素列に加えて、親 ID、名前、および型 ID のフル パス + 最上位の要素の 場所ID と名前のフル パスも返します。したがって、 ID 3 の要素を取得した場合(この条件は、ここで指定されていない複数の列によって複雑になる場合もあります)、クエリは次のように返す必要があります。
Id | ParentId | TypeId | Name | IdsPath | TypeIdsPath | NamesPath | LocIdsPath | LocNamesPath
---------------------------------------------------------------------------------------------------------------------------------------------------------------
3 | 2 | 11 | Level2Child | /3/2/1 | /11/11/10 | /Level2Child/Level1Child/TopParent | /102/101/100 | /Level2Location/Level1Location/TopLocation
最初に、場所と要素の目的のパスを返すオラクルの階層クエリを作成しました
位置
select
SYS_CONNECT_BY_PATH(Id, '/') IdsPath,
SYS_CONNECT_BY_PATH(Name, '/') NamesPath
from
loc
where
connect_by_isleaf = 1
CONNECT BY PRIOR ParentId = e.Id
start with Id = 102
エレメント
select
SYS_CONNECT_BY_PATH(Id, '/') IdsPath,
SYS_CONNECT_BY_PATH(TypeId, '/') TypeIdsPath,
SYS_CONNECT_BY_PATH(Name, '/') NamesPath
from
ele
where
connect_by_isleaf = 1
CONNECT BY PRIOR ParentId = e.Id
start with Id = 3
これらのクエリを基本選択で結合されたサブクエリとして使用したいときに問題が発生しました-階層クエリは完全なテーブルスキャンを実行するため、開始条件を結合条件に置き換えることはできません:
select
e.*,
elePath.IdsPath,
elePath.TypeIdsPath,
elePath.NamesPath,
locPath.IdsPath as LocIdsPath,
locPath.NamesPath as LocNamesPath
from
ele e
left join (
--full table scan!
select
CONNECT_BY_ROOT(Id) Id,
Id as TopEleId,
SYS_CONNECT_BY_PATH(Id, '/') IdsPath,
SYS_CONNECT_BY_PATH(TypeId, '/') TypeIdsPath,
SYS_CONNECT_BY_PATH(Name, '/') NamesPath
from ele
where
connect_by_isleaf = 1
CONNECT BY PRIOR ParentId = e.Id
) elePath on elePath.Id = e.Id
left join (
--full table scan!
select
CONNECT_BY_ROOT(Id) Id,
SYS_CONNECT_BY_PATH(Id, '/') IdsPath,
SYS_CONNECT_BY_PATH(Name, '/') NamesPath
from loc
where
connect_by_isleaf = 1
CONNECT BY PRIOR ParentId = e.Id
) locPath on locPath.Id = elePath.TopEleId
where
e.Id = 3
クエリは1つだけでなく複数のパスを返す必要があるため、スカラーサブクエリも実行できません。助言がありますか?私は正しい方向に進んでいますか、それとも要素テーブルにいくつかのフィールドを追加し、必要なすべてのパスをキャッシュする必要がありますか? (頻繁に更新されるわけではありません)
ありがとう!