Sql 选择与结果匹配的WHERE子句

Sql 选择与结果匹配的WHERE子句,sql,postgresql,Sql,Postgresql,我有一个数据库,我想做一个非常快速和粗略的地理哈希匹配。我想通过降低geohash的分辨率找到第一个最相似的匹配项,直到找到匹配项为止。下面的查询获取了我感兴趣的所有geohash,但我需要从下面的集合中选择一个与我的原始geohash最匹配的 SELECT business_address, geohash FROM geolocation WHERE geohash LIKE (CONCAT(SUBSTRING(:'geohash', 1, 12), '%')) OR

我有一个数据库,我想做一个非常快速和粗略的地理哈希匹配。我想通过降低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个单独的查询就能做到这一点呢?

这可能不是你想要的,但你可以用一个联合体来做到这一点。为每个查询添加一个固定列,设置返回结果集的优先级,并按此优先级对union中的最终结果集排序


它看起来像是六个查询(可能也会有同样的功能),但我认为没有其他方法。我不擅长查询优化,但最终结果可能会像后台的单个查询一样工作。

您可以通过为所有匹配项提供匹配的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


或者您可以根据需要进行更改。

您可以使用
生成_系列()

这将在上使用
DISTINCT,因为这通常比
GROUP BY
快,并允许您包含其他列

如果要比较的值不是真正的序列号,请使用
values()


(geohash,1,7)
我猜最接近,然后是
8,9,10..所有的
如果这是真的,我想知道使用PostGIS是否是解决这个问题的更好方法。它可以非常有效地进行“最近邻”搜索。这就解决了我的问题。我从来没有想过这一点,所以我想我还有很长的路要走。谢谢。
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;
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;