郵便番号、緯度と経度の表があります。半径と緯度と経度を受け取り、必要な半径内のすべての郵便番号を返す作業クエリがあります。
SELECT Zip.zip,
ROUND(SDO_GEOM.SDO_DISTANCE((MDSYS.SDO_GEOMETRY(2001, 4326, MDSYS.SDO_POINT_TYPE(:clng, :clat, NULL), NULL, NULL)), (
SELECT geom
FROM standard_Zip
WHERE Zip = Zip.zip
), 0.005) / 1609.34, 2) AS dist
FROM standard_Zip zip
WHERE Zip.zip IN (
SELECT DISTINCT (Zip) AS Zip
FROM standard_Zip c
WHERE SDO_FILTER(c.geom, SDO_UTIL.CIRCLE_POLYGON(:clng, :clat, :r, 5)) = 'TRUE'
AND SDO_RELATE(c.geom, SDO_UTIL.CIRCLE_POLYGON(:clng, :clat, :r, 5), 'mask=ANYINTERACT querytype = WINDOW') = 'TRUE'
)
ORDER BY DIST
Latとlongはすでにテーブルにあるので、最初に個別のルックアップを実行する代わりに、Zipコードをクエリの入力として提供したいのですが、これは永久に停止するようです。
SELECT
Zip.zip,
ROUND(SDO_GEOM.SDO_DISTANCE((MDSYS.SDO_GEOMETRY(2001, 4326, MDSYS.SDO_POINT_TYPE(inp.lng, inp.lat, NULL), NULL, NULL)), (SELECT geom FROM standard_Zip WHERE Zip = Zip.zip), 0.005) / 1609.34, 2) AS dist,
inp.lat,
inp.lng
FROM standard_Zip zip
LEFT JOIN (SELECT x as lng, y as lat from standard_Zip where Zip = :Zip) inp on 1=1
WHERE Zip.zip IN (
SELECT DISTINCT (Zip) AS Zip
FROM standard_Zip c
WHERE SDO_FILTER(c.geom, SDO_UTIL.CIRCLE_POLYGON(inp.lng, inp.lat, (:r * 1609.34), 5)) = 'TRUE'
AND SDO_RELATE(c.geom, SDO_UTIL.CIRCLE_POLYGON(inp.lng, inp.lat, (:r * 1609.34), 5), 'mask=ANYINTERACT querytype = WINDOW') = 'TRUE'
)
ORDER BY DIST
何が悪いのですか?
MguerraTorres 素晴らしいCTEを使用することをお勧めします。これが私が試したものです:
WITH inp as (SELECT x as lng, y as lat from standard_Zip where Zip = :Zip)
SELECT
Zip.zip,
ROUND(SDO_GEOM.SDO_DISTANCE((MDSYS.SDO_GEOMETRY(2001, 4326, MDSYS.SDO_POINT_TYPE(inp.lng, inp.lat, NULL), NULL, NULL)), (SELECT geom FROM standard_Zip WHERE Zip = Zip.zip), 0.005) / 1609.34, 2) AS dist,
inp.lat,
inp.lng
FROM standard_Zip zip
WHERE Zip.zip IN (
SELECT DISTINCT (Zip) AS Zip
FROM standard_Zip c
WHERE SDO_FILTER(c.geom, SDO_UTIL.CIRCLE_POLYGON(inp.lng, inp.lat, (:r * 1609.34), 5)) = 'TRUE'
AND SDO_RELATE(c.geom, SDO_UTIL.CIRCLE_POLYGON(inp.lng, inp.lat, (:r * 1609.34), 5), 'mask=ANYINTERACT querytype = WINDOW') = 'TRUE'
)
ORDER BY DIST
問題は、Oracleがinp.lng
は無効な識別子です。どうして?
「inp」クエリにクロス結合していますが、その結果をwhere句のメインのwhere句のサブクエリに使用しています。事実上、サブクエリはZipテーブルのすべての行に対して1回実行されます。少し遅くなります。
これに関してPL/SQLで実現できることについては、私は少し錆びているので、純粋なSQLでは次のように書くことができます。
SELECT
Zip.zip,
ROUND(SDO_GEOM.SDO_DISTANCE((MDSYS.SDO_GEOMETRY(2001, 4326, MDSYS.SDO_POINT_TYPE(inp.lng, inp.lat, NULL), NULL, NULL)), (SELECT geom FROM standard_Zip WHERE Zip = Zip.zip), 0.005) / 1609.34, 2) AS dist,
inp.lat,
inp.lng
FROM standard_Zip zip
WHERE Zip.zip IN (
SELECT DISTINCT (Zip) AS Zip
FROM standard_Zip c
WHERE SDO_FILTER(c.geom, SDO_UTIL.CIRCLE_POLYGON((SELECT x as lng from standard_Zip where Zip = :Zip),
(SELECT y as lat from standard_Zip where Zip = :Zip),
(:r * 1609.34), 5)) = 'TRUE'
AND SDO_RELATE(c.geom, SDO_UTIL.CIRCLE_POLYGON((SELECT x as lng from standard_Zip where Zip = :Zip),
(SELECT y as lat from standard_Zip where Zip = :Zip),
(:r * 1609.34), 5), 'mask=ANYINTERACT querytype = WINDOW') = 'TRUE'
)
ORDER BY DIST
もう少し速いかもしれません。基本的には、元の作業クエリとほぼ同じように動作するはずです。
私はそれがこれであるべきだと思います:
SELECT
Zip.zip,
ROUND(SDO_GEOM.SDO_DISTANCE((MDSYS.SDO_GEOMETRY(2001, 4326, MDSYS.SDO_POINT_TYPE(inp.lng, inp.lat, NULL), NULL, NULL)), (SELECT geom FROM standard_Zip WHERE Zip = Zip.zip), 0.005) / 1609.34, 2) AS dist,
inp.lat,
inp.lng
FROM standard_Zip zip
CROSS JOIN (SELECT x as lng, y as lat from standard_Zip where Zip = :Zip) inp
WHERE Zip.zip IN (
SELECT Zip
FROM standard_Zip c
WHERE SDO_FILTER(c.geom, SDO_UTIL.CIRCLE_POLYGON(inp.lng, inp.lat, (:r * 1609.34), 5)) = 'TRUE'
AND SDO_RELATE(c.geom, SDO_UTIL.CIRCLE_POLYGON(inp.lng, inp.lat, (:r * 1609.34), 5), 'mask=ANYINTERACT querytype = WINDOW') = 'TRUE'
)
ORDER BY DIST;
CTEを使用して試すことができます。
WITH CTE_Zip
AS
(SELECT DISTINCT (Zip) AS Zip
FROM standard_Zip c
WHERE SDO_FILTER(c.geom, SDO_UTIL.CIRCLE_POLYGON(:clng, :clat, :r, 5)) = 'TRUE'
AND SDO_RELATE(c.geom, SDO_UTIL.CIRCLE_POLYGON(:clng, :clat, :r, 5), 'mask=ANYINTERACT querytype = WINDOW') = 'TRUE')
次に、結合する標準テーブルと同じようにCTE_Zipテーブルを使用します。または、WHERE EXISTS/WHERE NOT EXISTSを使用することもできます。
SELECT Zip.zip,
ROUND(SDO_GEOM.SDO_DISTANCE((MDSYS.SDO_GEOMETRY(2001, 4326, MDSYS.SDO_POINT_TYPE(:clng, :clat, NULL), NULL, NULL)), (
SELECT geom
FROM standard_Zip
WHERE Zip = Zip.zip
), 0.005) / 1609.34, 2) AS dist
FROM standard_Zip zip
INNER JOIN CTE_Zip
ON Zip.zip = CTE_Zip.zip
ORDER BY DIST