PostgreSQL如何结合regex_split_to_array和foreach循环
PostgreSQL How to combine regex_split_to_array and foreach loop
我有一列包含多个逗号分隔值(最多 50 个国家/地区名称)。这些值必须替换为来自另一个 table.
的特定代码(国家代码,ISO3)
互联网搜索让我将这些值拆分为一个数组 (regex_split_to_array) and to use a loop through the array (FOREACH LOOP)
我了解了一般概念,但我至少在语法方面遇到困难(pqsl 初学者)。
方法:
DO
$do$
DECLARE
m varchar[];
arr varchar[]; -- declare array
BEGIN
-- split the comma-separeted values to array and insert into the array
SELECT (regexp_split_to_array(country, E','))
into arr
FROM tablename
WHERE xy;
FOREACH m SLICE 1 IN ARRAY arr
LOOP
-- update/replace the value with a function
RAISE NOTICE 'another function(%)', m;
END LOOP;
END
$do$
我假设填充数组不会那样工作..
PostgreSQL 9.1
您不需要循环或 PL/pgSQL。您可以使用一条语句完成此操作:
假设以下设置:
create table tablename
(
id integer primary key,
country_list text
);
create table lookup
(
iso_code varchar(3),
country text
);
insert into tablename
values
(1, 'Germany, Austria, Italy'),
(2, 'Austria, France'),
(3, 'France, Switzerland');
insert into lookup
values
('de', 'Germany'),
('at', 'Austria'),
('it', 'Italy'),
('fr', 'France'),
('ch', 'Switzerland');
您可以使用以下方式解除国家嵌套:
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s;
鉴于上面的示例数据 returns 以下内容:
id | country
---+------------
1 | Germany
1 | Austria
1 | Italy
2 | Austria
2 | France
3 | France
3 | Switzerland
这可以加入您的查找 table:
with normalized as (
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s
)
select n.id, n.country, l.iso_code
from normalized n
join lookup l on l.country = n.country;
这 returns 以下:
id | country | iso_code
---+-------------+---------
1 | Austria | at
1 | Germany | de
1 | Italy | it
2 | Austria | at
2 | France | fr
3 | France | fr
3 | Switzerland | ch
您可以将 ISO 代码列表聚合回您的反规范化结构中:
with normalized as (
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s
)
select n.id, string_agg(l.iso_code,',') as iso_list
from normalized n
join lookup l on l.country = n.country
group by n.id;
并且可用于替换目标中的值 table:
with normalized as (
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s
), translated as (
select n.id, string_agg(l.iso_code,',') as iso_list
from normalized n
join lookup l on l.country = n.country
group by n.id
)
update tablename st
set country_list = t.iso_list
from translated t
where t.id = st.id;
之后tablename
的内容是:
id | country_list
---+-------------
1 | it,at,de
2 | fr,at
3 | fr,ch
一个多更好的解决方案是正确规范化您的模型并在tablename
和[=之间创建多对多映射table 20=]
我有一列包含多个逗号分隔值(最多 50 个国家/地区名称)。这些值必须替换为来自另一个 table.
的特定代码(国家代码,ISO3)互联网搜索让我将这些值拆分为一个数组 (regex_split_to_array) and to use a loop through the array (FOREACH LOOP)
我了解了一般概念,但我至少在语法方面遇到困难(pqsl 初学者)。
方法:
DO
$do$
DECLARE
m varchar[];
arr varchar[]; -- declare array
BEGIN
-- split the comma-separeted values to array and insert into the array
SELECT (regexp_split_to_array(country, E','))
into arr
FROM tablename
WHERE xy;
FOREACH m SLICE 1 IN ARRAY arr
LOOP
-- update/replace the value with a function
RAISE NOTICE 'another function(%)', m;
END LOOP;
END
$do$
我假设填充数组不会那样工作..
PostgreSQL 9.1
您不需要循环或 PL/pgSQL。您可以使用一条语句完成此操作:
假设以下设置:
create table tablename
(
id integer primary key,
country_list text
);
create table lookup
(
iso_code varchar(3),
country text
);
insert into tablename
values
(1, 'Germany, Austria, Italy'),
(2, 'Austria, France'),
(3, 'France, Switzerland');
insert into lookup
values
('de', 'Germany'),
('at', 'Austria'),
('it', 'Italy'),
('fr', 'France'),
('ch', 'Switzerland');
您可以使用以下方式解除国家嵌套:
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s;
鉴于上面的示例数据 returns 以下内容:
id | country
---+------------
1 | Germany
1 | Austria
1 | Italy
2 | Austria
2 | France
3 | France
3 | Switzerland
这可以加入您的查找 table:
with normalized as (
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s
)
select n.id, n.country, l.iso_code
from normalized n
join lookup l on l.country = n.country;
这 returns 以下:
id | country | iso_code
---+-------------+---------
1 | Austria | at
1 | Germany | de
1 | Italy | it
2 | Austria | at
2 | France | fr
3 | France | fr
3 | Switzerland | ch
您可以将 ISO 代码列表聚合回您的反规范化结构中:
with normalized as (
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s
)
select n.id, string_agg(l.iso_code,',') as iso_list
from normalized n
join lookup l on l.country = n.country
group by n.id;
并且可用于替换目标中的值 table:
with normalized as (
select s.id, trim(unnest(string_to_array(s.country_list, ','))) as country
from tablename s
), translated as (
select n.id, string_agg(l.iso_code,',') as iso_list
from normalized n
join lookup l on l.country = n.country
group by n.id
)
update tablename st
set country_list = t.iso_list
from translated t
where t.id = st.id;
之后tablename
的内容是:
id | country_list
---+-------------
1 | it,at,de
2 | fr,at
3 | fr,ch
一个多更好的解决方案是正确规范化您的模型并在tablename
和[=之间创建多对多映射table 20=]