Postgresql 在复杂查询中连接两个表(非统一数据)

Postgresql 在复杂查询中连接两个表(非统一数据),postgresql,join,insert,data-migration,Postgresql,Join,Insert,Data Migration,我需要在一个查询中连接两个表,用于将数据插入第三个表(将来用于连接这两个表)。我将仅提及这些表中的相关列 PostgreSQL 9.0.5版 表1:数据表 迁移的数据,约10k行,相关列: id(主键) 地址(地址的开头,我需要与第二个表匹配的字符串。此地址具有不同的长度。) 表2:词典 字典,约9百万行,相关列: id(主键) 地址(完整地址,我需要与第一个表匹配的字符串,长度也不同。) 我到底需要什么 我需要在select语句中正确连接这些表,然后将它们插入第三个表。我所需要的只是一种成功连

我需要在一个查询中连接两个表,用于将数据插入第三个表(将来用于连接这两个表)。我将仅提及这些表中的相关列

PostgreSQL 9.0.5版

表1:数据表

迁移的数据,约10k行,相关列:

id(主键)

地址(地址的开头,我需要与第二个表匹配的字符串。此地址具有不同的长度。)

表2:词典

字典,约9百万行,相关列:

id(主键)

地址(完整地址,我需要与第一个表匹配的字符串,长度也不同。)

我到底需要什么

我需要在select语句中正确连接这些表,然后将它们插入第三个表。我所需要的只是一种成功连接这些表的方法

我想这样做的方式是从data_表中获取每个地址,并将其与字典中以data_table.address开头的第一个地址(edit:order by address asc)连接起来(不乘以记录,因为字典中的许多地址都以data_table.address开头)

另外,两个表中的addressess都包含很多不规则的空格,所以我们可能需要

replace(address, ' ', '') 
在这两个方面(欢迎任何其他想法)。由于dictionary有9百万行,而且服务器速度相当慢,因此可能还存在一些性能问题

我将结果视为以下查询的一些变体:

select 
data_table.id, dictionary_id
from
data_table, dictionary
where
-conditions-
orderby
在问题更新后更新。)如果没有
orderby
它会选择任意匹配项。
此相关答案中的技术说明:

词典上的功能索引会使这一点变得更快:

关于这一点,我在给客户的答复中做了更多解释


人们可能会争论这是否会让你成为“最佳”对手。另一种方法是使用三元索引进行相似性匹配。详细信息,请参见我添加到上一个问题的第一个链接。

我们的架构师提出的解决方案是编写一个函数来查找第一个匹配项

职能:

CREATE OR REPLACE FUNCTION pick_one_address(text)
  RETURNS text AS
$BODY$
DECLARE
  address_query text;
  toFind text;
  found text;
BEGIN

  toFind := (replace($1, ' ', '') || '%');  
  address_query := 'select al.id from dictionary al where replace(al.adres, '' '', '''') like ''' || toFind ||''' limit 1'; 
  EXECUTE address_query into found;
  RETURN found;

RETURN found_address;
END $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
代码可能看起来很奇怪,因为我确实更改了表名以保护公司的隐私,并且没有提到我用来简化问题的第三个表,但我想这应该足以理解该机制


感谢您的输入@ErwinBrandstetter、@CraigRinger

您在“PostgreSQL 9.0.5版”中失去了我。您有未修补的主要安全漏洞和次要可靠性/索引损坏问题。紧急升级。至于问题的其余部分:请提供样本数据和实际表格定义。我推荐+感谢你努力写一个像样的解释,并提及你的Pg版本。当你用样本数据编辑了你的问题,并解释了你已经尝试过的内容时,请在此处发表评论,以便通知我;我会尽力帮忙的。上下文前面的问题:请在
中定义“first”并将其与字典中的first address连接起来。没有定义就没有自然的第一。还是你可以随意挑选?加:数据表的基数(多少行)?@CraigRinger:谢谢你的建议。我的任务是一个庞大项目的一部分,要求升级不受我的影响。我现在下班回来了,没有访问数据库的权限,您想看一个完整的脚本来重新创建这些表吗?他们每个人大约有15个专栏,除了我发布的内容外,所有的专栏都是无关的。还有,有没有一种方法可以以可读的格式发布示例数据?ErwinBrandstetter:edited@fetta请将这些链接发送到您的管理层,然后:。如果他们不更新到9.0.13,那么我会非常担心这个项目。谢谢,我会在工作中尝试,并给你反馈,但据我所知,这正是我所需要的。我已经创建了索引并运行了查询,但使用
limit 5
子句,它现在运行了20分钟。我猜对于10k行,它根本不会执行。那么,其他的想法呢?我相信像
first\u值(substr(d.address,1,length(t.address)))超过(按t.address分区)
会更快,但是您不能在where子句中使用分析函数,我也不清楚如何使用它和/或如何连接这些表。@fetta:Window函数功能强大,但通常不会比类似于
的简单解决方案快。索引对于包含数百万行的表来说是必不可少的。一个简单的
解释
是否表明要使用索引?20分钟5行表示您的数据库严重损坏或以某种方式配置错误。
CREATE INDEX dictionary_address_text_pattern_ops_idx
ON dictionary (replace(address, ' ', '') text_pattern_ops);
CREATE OR REPLACE FUNCTION pick_one_address(text)
  RETURNS text AS
$BODY$
DECLARE
  address_query text;
  toFind text;
  found text;
BEGIN

  toFind := (replace($1, ' ', '') || '%');  
  address_query := 'select al.id from dictionary al where replace(al.adres, '' '', '''') like ''' || toFind ||''' limit 1'; 
  EXECUTE address_query into found;
  RETURN found;

RETURN found_address;
END $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;