2013-05-11 78 views
3

我有一個QSO(無線電聯繫)記錄的數據庫,我希望按站點國家彙總。該國家由電話呼號的前綴派生,如ITU Prefix List在連接字段的非重疊前綴時是否可以避免嵌套循環連接?

所定義的。不幸的是,這個前綴的長度是可變的。例如,以W開頭的所有內容都將分配給美國,但大多數國家/地區都由一個或多個2字符前綴標識。有些需要3個字符的前綴,例如,3DA到3DM是斯威士蘭,但3DN到3DZ是Fidji。

我可以建立一個表,像這樣:

CREATE TABLE country (
    prefix varchar(3) primary key, 
    country varchar(10) 
); 

和執行與比較難看錶達一個簡單的加入:

SELECT * from qso 
INNER JOIN country 
ON left(qso.callsign, length(country.prefix)) = country.prefix 

理解的是,這個執行使用嵌套循環聯接。這是有道理的,因爲如果沒有在我的國家/地區表中添加前綴的額外知識不會重疊,則此聯合可能會使多個國家/地區返回一個QSO。

現在,我可以使用一個醜陋的黑客,並在我的prefix表中插入所有明確的3個字符的前綴,並使用平等連接。這會增加我的前綴表的大小150倍,但自然允許使用哈希或合併加入。

但是,我的前綴不重疊​​,而且QSO已經通過呼號進行索引,所以有一個明顯高效的類似合併算法來執行此聯接。

有沒有什麼辦法可以將Postgres引導到我所想的連接算法?也許使用一個奇特的索引類型,或者一個特殊的匹配運算符?

注:通聯表是這樣的:

CREATE TABLE qso (
    time_on timestamp primary key, 
    callsign varchar(10), 
    ... 
); 
CREATE INDEX qso_callsign ON qso(callsign); 
+0

什麼是qso表結構? – 2013-05-11 22:07:50

+0

將其添加到帖子中,但它可能與問題無關。 – b0fh 2013-05-11 22:16:02

+0

你有沒有想過打破呼號分兩部分,前綴和其他?那有什麼問題?在問題中加入 – 2013-05-11 22:26:18

回答

0

我認爲最好的辦法是將所有三個字符的前綴添加到country表。我不明白這會如何增加「150倍」。假設代碼有26個大寫字母和10個數字,這最多會增加36次。但是,大多數代碼可能沒有國家,因此數量會少得多 - 只是實際分配給國家的3字符代碼的數量。

另一種方法是做兩聯接這樣的:

select qso.*, coalesce(c3.whatever, c2.whatever) -- use the c3 version first, then the c2 version 
from qso left outer join 
    country c2 
    ON left(qso.callsign,2) = c2.prefix left outer join 
    country c3 
    on left(qso.callsign, 3) = c3.prefix; 

這些連接應在country表使用索引。如果你把它封裝在一個視圖中,那麼其他代碼就可以使用它。

+0

好吧,大約有300個定義的範圍,而有36^3個可能的三字母前綴,但是,這是一個粗糙的背後估計。以不同大小的固定通行證進行連接是一個非常有趣的想法,我必須更多地考慮它 – b0fh 2013-05-11 22:35:49

1

這似乎是一個正確的方法來做到這一點將是定義一個自定義的前綴匹配函數與CREATE OPERATOR,並將其標記爲可合併連接通過MERGES條款。當我測試這個確實有效時,我會編輯這個答案。

另一種可能是使用有限的子查詢來查找比呼號更小的「最大」前綴,如自然歸類順序所定義的 - 可能更自然。