查找(更大)最接近联接表的值

时间:2019-07-11 12:27:39

标签: postgresql join

我的PostgreSQL中有两个表。

  • 地址(街道,城市,邮政编码)
  • 邮政编码(zip,gps_lat,gps_long)

ZIP都为CHAR(5),但每个ZIP的格式均为:“ XXXXX” 5个数字。例如:“ 55555”或“ 12345”。

我要选择所有已加入ZIP的地址。 问题是,某些地址带有zip,而该地址不在ZIP表中。在这种情况下,我想加入NEAREST(BIGGER)的zip值。

我为此创建了DB函数(psc == zip):

CREATE OR REPLACE FUNCTION lekari.get_psc(pscx character)
RETURNS character
LANGUAGE plpgsql
AS $function$
begin
    if exists (select 1 from spravni_celky.zip where psc = pscx) then
        return pscx;
    end if;

    while not exists (select 1 from spravni_celky.zip where psc = pscx) loop  
        pscx =  cast(cast(pscx as integer) + 1 as char(5));
    end loop;

return pscx;
end;$function$;

然后创建,只需选择:

select * from lekari.address lad
join spravni_celky.zip p on p.psc = lekari.get_psc(lad.psc)

它可以工作,但是对于ADDRESS中的12行(ZIP中约200行),查询时间几乎是 4分钟

计划B在DB中存储了两个ZIP,一个当前,另一个用于联接。

非常感谢!

2 个答案:

答案 0 :(得分:2)

demo:db<>fiddle

SELECT DISTINCT ON (a.city, a.street, a.zip)
    *
FROM
    address a
JOIN
    zip z
ON a.zip <= z.zip
ORDER BY a.city, a.street, a.zip, z.zip

加入等于或更大的所有ZIP。然后给出每个加入地址的第一条记录。

如果zip存在:第一个适合的ZIP等于。因此,第一个排序的记录是自己的邮政编码。

如果zip不存在:第一个合适的ZIP是下一个更大的ZIP。

DISTINCT ON给出有序组的第一条记录。

答案 1 :(得分:0)

您已经对所提出的问题有了答案,并且对策略整体有了一些评论。我只是想跳到后面的观点,因为在前世,我写了一个邮政编码距离计算器产品。很好,回到Internet之前,但是我现在不推荐。原因如下:

  • 有负担得起的API,可以进行路边精度的距离和接近度计算。比粗质心计算好得多。我会时不时地进行调查,但是现在不知道最好的解决方案是什么。

  • 如果您更新了经纬度坐标,那么球面上距离的数学就非常基础了。到处都有例子。不是超高保真度,而是快速。对于阻止查询,您希望在进行更敏感的搜索之前将其过滤到一个粗糙区域,这有点好。 Postgres有一个点类型,但也许您已经在使用它。 (我相信,PostGIS支持R树,这是用于真实多边形的非常棒的索引结构。)

  • 如果必须使用邮政编码重心,则必须定期更新数据。没有可靠的方法来为缺少的邮政编码插入坐标,您必须去获取有人计算出的坐标(“组成”,请参阅下一点。)这是USPS提供的功能: https://www.unitedstateszipcodes.org/zip-code-database/

  • “中心?”正如人们已经指出的,邮政编码是路线,而不是多边形。因此多边形被伪造了。然后人为选择一个中心点。它可能在湖中,而不是高保真点数据集。

  • 具有简单触发的质心数据在很长的距离上都可以正常工作,而在密集区域则效果不佳。因此,人口越密集,结果越差。好吧,由于世界不是一个球体,从海岸到海岸也会使事情变得混乱。

  • ZIP代码的数字顺序不是用于衡量接近程度。几个词:夏威夷,关岛,北马里亚纳群岛,帕劳,阿拉斯加。

  • 听起来您已经覆盖了前导零,例如01776。太好了。某些地区的开发人员(加利福尼亚,你好,我在看着你!)忘记了马萨诸塞州等邮政编码为首位为0的地方。

  • 您显然正在处理美国数据,这通常会引发一个问题:“加拿大情况如何?”不。根据皇室法令,加拿大每10个人就有一个邮政编码。为此,使用路边一级的地址服务确实会更好。