我有一个QSO(无线电联系)记录数据库,我想按车站国家汇总。该国家/地区源自电台呼号的前缀,由ITU Prefix List
定义不幸的是,这个前缀的长度可变。例如,以W开头的所有内容都分配给美国,但大多数国家/地区都由一个或多个双字符前缀标识。有些需要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已经被callign索引,因此有一种明显有效的类似合并的算法来执行此连接。
有没有办法让Postgres加入我想到的连接算法?也许使用花式索引类型或特殊匹配运算符?
注意:QSO表类似于:
CREATE TABLE qso (
time_on timestamp primary key,
callsign varchar(10),
...
);
CREATE INDEX qso_callsign ON qso(callsign);
答案 0 :(得分:1)
执行此操作似乎是一种正确的方法是使用CREATE OPERATOR
定义自定义前缀匹配函数,并通过MERGES
子句将其标记为可合并。当我测试这确实有效时,我会编辑这个答案。
另一种可能是使用有限的子选择来查找小于呼号的“最大”前缀,如自然归类顺序所定义的那样 - 可能更自然。
答案 1 :(得分: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
表上的索引。如果你将它封装在一个视图中,那么其他代码就可以使用它。