我有一个数据库,我想在其中进行快速而粗糙的geohash匹配。我想通过降低geohash的分辨率来找到第一个,最相似的匹配项,直到获得成功为止。以下查询为我提供了所有我感兴趣的geohash,但是我需要从以下集合中选择与我的原始geohash最接近的匹配。
SELECT business_address, geohash FROM geolocation
WHERE
geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 12), '%')) OR
geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 11), '%')) OR
geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 10), '%')) OR
geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 9), '%')) OR
geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 8), '%')) OR
geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 7), '%'));
问题是我没有明确的方法来订购此结果,也没有添加可用于订购结果的列。仅将结果限制为1并按geohash排序是不够的,因为较低分辨率的匹配项可能位于全分辨率geohash的两侧。有没有一种方法可以让我无需执行6个单独的查询?
答案 0 :(得分:2)
您可以通过为所有匹配项提供匹配的slno,然后找到最小的slno以获得最接近的匹配项来做到这一点
WITH CTE AS (
SELECT business_address, geohash, 12 AS SLNO FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 12), '%'))
UNION ALL
SELECT business_address, geohash, 11 FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 11), '%'))
UNION ALL
SELECT business_address, geohash, 10 FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 10), '%'))
UNION ALL
SELECT business_address, geohash, 9 FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 9), '%'))
UNION ALL
SELECT business_address, geohash, 8 FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 8), '%'))
UNION ALL
SELECT business_address, geohash, 7 FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 7), '%'));
)
SELECT business_address, geohash, MIN(SLNO) AS SLNO FROM CTE --- change MIN(Slno) as per your need
GROUP BY business_address, geohash
或者您可以根据需要进行更改。
答案 1 :(得分:0)
这可能与您要查找的不完全相同,但是您可以使用联合来执行此操作。在每个查询中添加一个固定列,设置返回结果集的优先级,并以此优先级从联合中订购最终结果集。
它看起来像六个查询(也许也可以这样),但是我认为没有其他方法。我不擅长查询优化,但是最终结果有可能实际上像在后台执行单个查询一样。
答案 2 :(得分:0)
您可以使用generate_series()
:
SELECT DISTINCT ON (gl.business_address) gl.business_address, gl.geohash
FROM geolocation gl JOIN
generate_series(12, 7, -1) gs(val)
ON gl.geohash LIKE SUBSTRING(:'geohash', 1, gs.val) || '%')
ORDER BY gl.business_address, gl.geohash ASC;
之所以使用DISTINCT ON
,是因为它通常比GROUP BY
快,并且允许您包含其他列。
如果要比较的值不是真正的连续数字,请使用VALUES()
:
SELECT DISTINCT ON (gl.business_address) gl.business_address, gl.geohash
FROM geolocation gl JOIN
(VALUES (12), (11), (10), (9), (8), (7)) v(val)
ON gl.geohash LIKE SUBSTRING(:'geohash', 1, v.val) || '%')
ORDER BY gl.business_address, gl.geohash ASC;