Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在连接字段的非重叠前缀时,是否可以避免嵌套循环连接?_Sql_Postgresql - Fatal编程技术网

Sql 在连接字段的非重叠前缀时,是否可以避免嵌套循环连接?

Sql 在连接字段的非重叠前缀时,是否可以避免嵌套循环连接?,sql,postgresql,Sql,Postgresql,我有一个QSO(无线电联络)记录的数据库,我想按国家电台汇总。国家/地区来源于电台呼号的前缀,如 不幸的是,这个前缀的长度是可变的。例如,以W开头的所有内容都分配给美国,但大多数国家都由一个或多个2字符前缀标识。有些需要3个字符的前缀,例如,3DA到3DM是斯威士兰,但3DN到3DZ是Fidji 我可以这样构建一个表: CREATE TABLE country ( prefix varchar(3) primary key, country varchar(10) ); 并使用

我有一个QSO(无线电联络)记录的数据库,我想按国家电台汇总。国家/地区来源于电台呼号的前缀,如

不幸的是,这个前缀的长度是可变的。例如,以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
可以理解,这使用嵌套循环执行连接。这是有道理的,因为如果不知道我的国家表中的前缀不会重叠,这种连接可能会为单个类星体返回多个国家

现在,我可以使用一个丑陋的hack,在我的
prefix
表中插入所有显式的3字符前缀,并使用相等联接。这将使前缀表的大小增加150倍,但自然允许使用哈希或合并联接

但是,我的前缀没有重叠,QSO已经通过呼号索引,因此有一个明显的高效合并算法来执行这种连接

有没有什么方法可以让Postgres使用我正在考虑的连接算法?可能使用一个奇特的索引类型,或者一个特殊的匹配操作符

注:QSO表类似于:

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

我认为最好的办法是将所有三个字符的前缀添加到
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;

这些联接应使用
国家/地区
表上的索引。如果您将其封装在视图中,那么其他代码就可以使用它。

这样做的一个正确方法似乎是使用
CREATE操作符定义一个自定义前缀匹配函数,并通过
MERGES
子句将其标记为merge joinable。当我测试过这确实有效时,我会编辑这个答案


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

什么是qso表结构?将其添加到帖子中,但可能与问题无关。我认为维基百科条目是错误的,列支敦士登使用HB0(HB0Y用于新手许可证),而瑞士仅在HB范围内使用HB9(用于完整许可证)和HB3(用于新手许可证)。瑞士肯定使用HB3Y。我怀疑您可以在
上使用复合索引(前缀长度,前缀)
,但我不能随意创建示例数据。如果您发布了一些示例数据,我会试试。如果前缀、国家或呼号(及时)不稳定你会有一个可怕的数据建模噩梦。例如:拆分后,Yougoslavian前缀和呼号发生了什么事?好吧,大约有300个定义范围,而有36^3个可能的三个字母前缀,但是是的,这是一个粗略的信封估算。在不同大小的固定通道中进行连接是一个非常复杂的过程这个主意很有趣,我得多想想