我使用修改后的预订树在我的应用程序中将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 - 城市)。如您所见,克里特岛被存储为城市,其中包含其他城市(例如Vamos
和Rethymno
)作为其子女。
我需要执行两种类型的查询:
1)获取特定父级下特定类型的所有位置。
2)获取特定父级下特定类型的所有顶级位置:对于提供的位置示例,在查询希腊境内的城市时应返回Crete Isl.
,因为Crete Isl.
没有父类型城市,而城市Vamos
和Rethymno
拥有城市类型的父级 - Crete Isl.
在每种情况下执行的最快查询是什么?
对于第一种情况,我考虑使用两个查询(首先,获取希腊的LFT和RGT,第二个获取类型= 4的所有位置,具有适当的LFT和RGT)或使用某种类型的连接来获取所有位置一步到位哪种方法最好?
对于第二种情况,我目前没有任何合适的想法。我尝试过简单的子选择:
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;
但它太长了。
我不介意添加更多列并使用一些值填充它们,这将有助于加快这两种类型的查询。但我需要快速获取数据。
感谢。
答案 0 :(得分:1)
对于ID
给出: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
:id
givien 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
以及条件child
会删除那些location
记录,其中child
的后代是{{1}}的祖先。< / p>
答案 1 :(得分: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
简单加入。
对于你的第二个问题,也许是这样的。找到父级,然后从中找到正确类型下面的所有记录。找到这个孩子的同一类型的父母。如果找到一个,则忽略。
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