2017-09-20 10 views
0

複数のカンマ区切りの値(国名は50まで)の列があります。これらの値は、別のテーブルの特定のコード(国コード、ISO3)に置き換える必要があります。PostgreSQL regex_split_to_arrayとforeachループを組み合わせる方法

インターネット検索は、配列に値を分割する(regex_split_to_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

+0

間の多対多マッピングテーブルを作成することですそしてなぜあなたはサポートされていなくて古くなったPostgresバージョンを使用していますか? –

+0

私はサーバー管理者ではありません、私はそれについて知っており、すでにそれを報告しました。ありがとう。 –

答えて

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; 

は次の値を返します。

id | country  
---+------------ 
1 | Germany  
1 | Austria  
1 | Italy  
2 | Austria  
2 | France  
3 | France  
3 | Switzerland 

ルックアップテーブルに追加することができます。

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; 

これには次の値を返します。

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; 

そして、それを置き換えるために使用することができます目標表の値:

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  

ずっとより良い解決策が適切にあなたのモデルを正規化し、tablenamelookup_table

関連する問題