1

我有一个非常常见的地址数据库设置:apersoncompany带有连接表的 a 相关联,company可以有 anaddress等等。

所有这些都非常规范且易于使用。但是对于搜索性能,我正在创建一个物化的,而不是非规范化的视图。我只需要一组非常有限的信息和快速查询。通常通过连接表完成的大多数事情现在都在一个数组中。根据查询,我可以直接搜索或通过unnest.

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

我的映射日期在这样的表中:

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 位数字,我可以创建一个大表映射 zip 来直接声明,而不是通过一个范围来做(我目前最喜欢的,但丑陋到足以让我问是否有更好的方法)

有什么方法可以在 SQL 中使用上面的表(或类似的表)来做到这一点?我在 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,
4

1 回答 1

1

我建议使用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;

如果保证了参照完整性,则根本不需要加入表company。我走捷径。

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

有关的:

于 2015-09-18T03:13:09.187 回答