Mat*_*att 6 postgresql full-text-search pattern-matching update postgresql-9.4
我有 2 个看起来像这样的表:
表一:
CREATE TEMP TABLE table_a (
Column_1 text,
ID_number int
);
INSERT INTO table_a VALUES
('foo,bar,baz', 123),
('qux,quux,quuz',456),
('corge,grault,garply',789),
('qux,bar,grault', 101);
Run Code Online (Sandbox Code Playgroud)
表 B:
CREATE TEMP TABLE table_b (
Column_1 text,
Column_2 text,
ID_number int
);
INSERT INTO table_b VALUES
('foo','baz',null),
('qux','quzz',null),
('corge','garply',null);
Run Code Online (Sandbox Code Playgroud)
我正在尝试从表 A 中的 ID_number 列复制值,其中表 B 的第 1 列和第 2 列中的值可以在表 A 的第 1 列的同一行中找到。
这是我在想的事情:
UPDATE table_b AS B
SET id_number = A.id_number
FROM table_a AS A
WHERE A.column_1 LIKE B.column_1
AND A.column_1 LIKE B.column_2
Run Code Online (Sandbox Code Playgroud)
.. 但显然这行不通。
如何将其转换为正确的查询?
附加信息
table_a.Column_1
包含英国地址,例如:
'47 BOWERS PLACE, GREAT YARMOUTH, NORFOLK, NR20 4AN'
Run Code Online (Sandbox Code Playgroud)
在table_b
我有地址的第一行Column_1
(so, '47 BOWERS PLACE'
) 和邮政编码 ( 'NR20 4AN'
) 在Column_2
.
我认为最好简化事情,但也许实际数据在这种情况下有一些相关性。
table_a
有大约 3000 万个地址。table_b
有大约 60k 行。
性能是相关的,运行得越快越好,并且将来可能会重复。
这里的关键是Column_1
,代表 JOIN 的三个可能值。所以你想要使用的是string_to_array()
(只要这些值是逗号分隔的并且本身不能包含逗号)。
运行这个查询,
SELECT id_number, string_to_array(column_1, ',') AS column_1
FROM table_a;
id_number | column_1
-----------+-----------------------
123 | {foo,bar,baz}
456 | {qux,quux,quuz}
789 | {corge,grault,garply}
101 | {qux,bar,grault}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以运行我们的UPDATE
using = ANY()
,
UPDATE table_b
SET id_number = A.id_number
FROM (
SELECT id_number, string_to_array(column_1, ',') AS column_1
FROM table_a
) AS A
WHERE table_b.column_1 = ANY(A.column_1)
AND table_b.column_2 = ANY(A.column_1);
Run Code Online (Sandbox Code Playgroud)
您也可以使用 <@
WHERE ARRAY[table_b.column_1, table_b.column_2] <@ A.column_1;
Run Code Online (Sandbox Code Playgroud)
这甚至使它更紧凑一点..
UPDATE table_b
SET id_number = A.id_number
FROM table_a AS A
WHERE ARRAY[table_b.column_1, table_b.column_2] <@ string_to_array(A.column_1, ',');
Run Code Online (Sandbox Code Playgroud)
尝试这个:
update table_b
set id_number = (select id_number
from table_a
where table_a.Column_1 like '%' || table_b.Column_1 || '%'
OR table_a.Column_1 like '%' || table_b.Column_2 || '%'
limit 1)
;
Run Code Online (Sandbox Code Playgroud)
通过将 Column_1 转换为数组可以是另一种解决方案,但这很清楚。
请注意,我将搜索限制为 1 条记录,以防文本出现在 Table_A 的多个 column_1 中。
正如埃文卡罗尔在评论部分指出的那样,我会注意到这段代码更新了整个表格。
在这里检查:http : //rextester.com/MUL4593
假设Postgres 9.6,性能相关,大表,由字符组成的“单词”,没有空格或标点符号,没有词干或停止词,没有短语,所有列NOT NULL
。
由索引支持的全文搜索应该是最快的解决方案之一:
UPDATE table_b b
SET id_number = a.id_number
FROM table_a a
WHERE to_tsvector('simple', a.column_1)
@@ plainto_tsquery('simple', concat_ws(' ', b.column_1, b.column_2))
AND b.id_number = a.id_number; -- prevent empty UPDATEs
Run Code Online (Sandbox Code Playgroud)
具有匹配的表达式索引a.column_1
:
CREATE INDEX table_a_column_1_idx ON table_a USING GIN (to_tsvector('simple', column_1));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4894 次 |
最近记录: |