0

修正されたプレオーダー ツリーを使用して、アプリケーションの GEO ロケーションを単一のテーブル LOC_TABLE に格納します。たとえば、ギリシャのサブツリーの例は次のようになります。

+-------+---------------+-----+-----+------+
| ID    | NAME          | LFT | RGT | TYPE |
+-------+---------------+-----+-----+------+
|    10 | Greece        | 100 | 200 |   3  |
|    20 | Crete Isl.    | 120 | 140 |   4  |
|    25 | Crete-Vamos   | 121 | 122 |   4  |
|    26 | Crete-Rethymno| 123 | 124 |   4  |
 ....
+-------+---------------+-----+-----+------+

TYPE列は、場所のタイプ (3 - 国、4 - 都市) を格納するために使用されます。ご覧のように、Crete は city として格納されており、その子として他の都市 (Vamosと など) が含まれています。Rethymno

次の 2 種類のクエリを実行する必要があります。

1) 特定の親の下にある特定のタイプのすべての場所を取得します。

2) 特定の親の下にある特定のタイプの上位のすべての場所を取得します: 提供された例では、ギリシャ国内の都市を照会する場合にのみ、場所の例を返す必要Crete Isl.があります。Crete Isl.VamosRethymnoCrete Isl.

それぞれのケースで実行する最速のクエリは何ですか?

最初のケースでは、2 つのクエリを使用する (最初にギリシャの LFT と RGT を取得し、次に適切な LFT と RGT を持つタイプ = 4 のすべての場所を取得する) か、何らかの結合を使用して 1 つのステップですべての場所を取得することを検討します。 . 最適なアプローチはどれですか?

2番目のケースについては、現在適切なアイデアがありません。私は単純なサブセレクトを試しました:

select loc.* from LOC_TABLE loc 
where 4 not in 
(select TYPE from LOC_TABLE p 
    where p.lft < loc.lft AND p.rgt > loc.rgt) 
AND loc.LFT > 100 AND loc.RGT < 200;

しかし、長すぎます。

これら 2 種類のクエリを高速化するのに役立つ列を追加して値を設定しても構いません。しかし、データをすばやく取得する必要があります。

ありがとう。

4

2 に答える 2

1

私はこれらのようなものを試してみます:-

SELECT b.*
FROM LOC_TABLE a
INNER JOIN LOC_TABLE b
ON a.LFT < b.LFT AND a.RGT > b.RGT
WHERE a.ID = 10
AND b.TYPE = 4

単純な結合。

2番目の質問については、おそらく次のようなものです。親を見つけて、そこから正しいタイプの下にあるすべてのレコードを見つけます。この子の同じタイプの親を見つけます。見つかった場合は無視します。

SELECT b.*
FROM LOC_TABLE a
INNER JOIN LOC_TABLE b ON a.LFT < b.LFT AND a.RGT > b.RGT
LEFT JOIN LOC_TABLE c ON c.LFT > b.LFT AND c.RGT < b.RGT AND b.TYPE = c.TYPE
WHERE a.ID = 10
AND b.TYPE = 4
AND c.ID IS NULL
于 2013-04-15T11:16:33.233 に答える
1

ID指定された byを持つ特定のレコードの都市および子孫であるすべてのレコードに対して、次:idを使用します。

SELECT descendant.ID, descendant.NAME, descendant.TYPE 
FROM LOC_TABLE location
INNER JOIN LOC_TABLE descendant
    ON descendant.LFT > location.LFT AND descendant.RGT < location.RGT
WHERE location.ID = :id AND TYPE = 4

ID都市であり、与えられたbyを持つレコードの子であるすべてのレコードに対して、次:idを使用します。

SELECT child.ID, child.NAME, child.TYPE 
FROM LOC_TABLE location
INNER JOIN LOC_TABLE child
    ON child.LFT > location.LFT AND child.RGT < location.RGT
LEFT OUTER JOIN LOC_TABLE intermediate
    ON intermediate.LFT < child.LFT
    AND intermediate.RGT > child.RGT
    AND intermediate.LFT > location.LFT
    AND intermediate.RGT < location.RGT
WHERE location.ID = :id
AND child.TYPE = 4
AND intermediate.ID IS NULL

LEFT OUTER JOIN条件付きのは、 の祖先であるの子孫があるレコードを除外しintermediate.ID IS NULLます。childlocationchild

于 2013-04-15T11:06:48.957 に答える