[英]Subquery that matches column with several ranges defined in table
我已經為地址數據庫設置了一個非常普通的設置:一個person
通過聯接表綁定到一家company
,該company
可以有一個address
,依此類推。
所有這些都非常標准化並且易於使用。 但是為了提高搜索性能,我正在創建一個物化的,相當規范化的視圖。 我只需要非常有限的信息和快速查詢集。 現在通常通過連接表完成的大多數操作現在都在數組中。 根據查詢,我可以直接搜索它,也可以通過unnest
加入它。
作為補充,以我的zipcodes
列( varchar[]
我想補充一個states
具有(德國fedaral)列國家已經預先計算,這樣我就不必變換查詢,包括各種范圍比較。
我的映射日期在這樣的表中:
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,
我建議使用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
。 我走了捷徑。
請注意, varchar
或text
行為與預期的數字不同。 例如: '333' > '0999'
。 如果所有郵政編碼都有5位數字,則可以。
有關:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.