与 table 中定义的多个范围相匹配的列的子查询

Subquery that matches column with several ranges defined in table

我有一个非常常见的地址数据库设置:person 通过连接 table 绑定到 companycompany 可以有address 等等。

一切都非常标准化且易于使用。但是为了搜索性能,我创建了一个物化的、非规范化的视图。我只需要一组非常有限的信息和快速查询。大多数通常通过连接 table 完成的事情现在都在一个数组中。根据查询,我可以直接搜索它或通过 unnest.

加入它

作为对我的 zipcodes 列 (varchar[]) 的补充,我想添加一个 states 列,其中已经预先计算了(德国联邦)州,以便我不必转换查询以包含各种范围比较。

我的映射日期是这样的table:

CREATE TABLE zip2state (
    state TEXT NOT NULL,
    range_start CHARACTER VARYING(5) NOT NULL,
    range_end CHARACTER VARYING(5) NOT NULL
)

每个州都有多个范围,范围可以重叠(一个邮政编码可以代表两个不同的州)。有些范围有 range_start = range_end.

现在我对如何一次性将其全部转换为实体化视图有些不知所措。通常,我很想迭代地执行它(通过触发器或在应用程序级别)。 或者当我们只讨论 5 位数字时,我可以创建一个大的 table 映射 zip 直接映射到 state,而不是通过一个范围来做(我目前最喜欢的,但有些丑陋到让我问是否有更好的方法)

有什么方法可以在 SQL 中用上面的 table(或类似的东西)做到这一点?我在 postgres 9.3,允许所有功能...

为了完整起见,这里是邮政编码的子查询:

    (select array_agg(distinct address.zipcode)
      from  affiliation
      join  company
        on  affiliation.ins_id = company.id
      join  address
        on  address.com_id = company.id
     where  affiliation.per_id = person.id) AS zipcodes,

我建议使用 LATERAL 连接而不是相关子查询,以便同时计算两列。可能看起来像这样:

SELECT p.*, z.*
FROM   person p
LEFT   JOIN LATERAL (
   SELECT array_agg(DISTINCT d.zipcode) AS zipcodes
        , array_agg(DISTINCT z.state)   AS states
   FROM   affiliation    a
   -- JOIN   company     c ON a.ins_id = c.id  -- suspect you don't need this
   JOIN   address        d ON d.com_id = a.ins_id  -- c.id
   LEFT   JOIN zip2state z ON d.zipcode BETWEEN z.range_start AND z.range_end
   WHERE  a.per_id = p.id
   ) z ON true;

如果引用完整性得到保证,您根本不需要加入 table company。我走了捷径。

请注意,varchartext 的行为与数字的预期不同。例如:'333' > '0999'。如果 所有 邮政编码有 5 位数字,你就可以了。

相关: