3

我有一个 QSO(无线电联系)记录数据库,我想按电台国家汇总。国家来自电台呼号的前缀,由ITU 前缀列表定义

不幸的是,这个前缀是可变长度的。例如,以 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 返回多个国家/地区。

现在,我可以使用丑陋的 hack,在我的prefix表中插入所有明确的 3 字符前缀,并使用等式连接。这将使我的前缀表的大小增加 150 倍,但自然允许使用 Hash 或 Merge Join。

但是,我的前缀不重叠​​,并且 QSO 已经被呼号索引,所以有一个明显有效的类似合并的算法来执行这个连接。

有什么方法可以将 Postgres 引入我正在考虑的连接算法?也许使用花哨的索引类型或特殊的匹配运算符?

注意:QSO 表类似于:

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

2 回答 2

1

似乎一种正确的方法是使用 定义自定义前缀匹配函数,并通过子句CREATE OPERATOR将其标记为可合并连接。MERGES当我测试这确实有效时,我会编辑这个答案。

另一种可能是使用有限的子选择来查找小于呼号的“最大”前缀,如自然排序顺序所定义的那样——这可能更自然。

于 2013-05-12T00:45:29.923 回答
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表上的索引。如果你将它封装在一个视图中,那么其他代码就可以使用它。

于 2013-05-11T22:31:41.547 回答