Как сократить код в PostgreSQL при использовании UPDATE
Работаю с PostgreSQL 12.7 и у меня возникла проблема с большим количеством однотипного кода , порядком 400 строк. хочу найти альтернативу что бы хотя бы сократить в двое такое количество строк. Пользовался некой заменой одних данных на другие с помощью функции UPDATE. Недавно нашел функцию similarity , но не понимаю как её правильно применить. Вот 2 строчки из той кучи.
UPDATE "DataB" SET "consignee_country" = 'VA' WHERE "consignee_country" in ('HolySee(VaticanCityState)' , 'ВЕНЕСУЭЛАБОЛИВАРИАНСКАЯРЕСПУБЛИКА' , 'HOLYSEE(VATICANCITYSTATE)' , 'HOLYSEE' , 'ВенесуэлаБоливарианскаяРеспублика');
и
UPDATE "DataB" SET "country_of_shipping" = 'VA' WHERE "country_of_shipping" in ('HolySee(VaticanCityState)' , 'ВЕНЕСУЭЛАБОЛИВАРИАНСКАЯРЕСПУБЛИКА' , 'HOLYSEE(VATICANCITYSTATE)' , 'HOLYSEE' , 'ВенесуэлаБоливарианскаяРеспублика');
"DataB" Это таблица , а "country_of_shipping" , "consignee_country" это столбцы. Хочу объединить две этих строки в одно , если у вас есть альтернатива по лучше , то предлагайте , очень поможет.
Одина из моих неудачних попиток :
UPDATE "DataB" SET consignee_country = 'VA' or country_of_shipping = 'VA' WHERE (consignee_country or country_of_shipping) in ('HolySee(VaticanCityState)' , 'ВЕНЕСУЭЛАБОЛИВАРИАНСКАЯРЕСПУБЛИКА' , 'HOLYSEE(VATICANCITYSTATE)' , 'HOLYSEE' , 'ВенесуэлаБоливарианскаяРеспублика');
Я понимаю что это глупо даже со стороны логики и особо размер не уменьшило хотя и стало одной строчкой.
Ответы (2 шт):
Можно сделать так. Сначала создать таблицу с соответствием кодов (VA) и названий (HOLYSEE и прочее):
create table mapping as (
select code, unnest(title) title from (
values ('VA', ARRAY['HolySee(VaticanCityState)' , 'ВЕНЕСУЭЛАБОЛИВАРИАНСКАЯРЕСПУБЛИКА' , 'HOLYSEE(VATICANCITYSTATE)' , 'HOLYSEE' , 'ВенесуэлаБоливарианскаяРеспублика']::TEXT[])
union all
values ('UK', ARRAY['United Kingdom' , 'Великобритания']::TEXT[])
union all
values ('US', array['USA', 'США']::text[])
) as t(code, title));
И теперь можно двумя запросами обновить все записи:
update "DataB" as d
set country_of_shipping = code
from mapping m
where d.country_of_shipping = m.title;
update "DataB" as d
set consignee_country = code
from mapping m
where d. consignee_country = m.title;
После этого таблицу mapping можно удалить.
create table DataB (consignee_country text, country_of_shipping text);
insert into DataB values('USA', 'США');
insert into DataB values('RU', 'RU');
with mapping as (
select 'VA' code , ARRAY['HolySee(VaticanCityState)' , 'ВЕНЕСУЭЛАБОЛИВАРИАНСКАЯРЕСПУБЛИКА' , 'HOLYSEE(VATICANCITYSTATE)' , 'HOLYSEE' , 'ВенесуэлаБоливарианскаяРеспублика']::TEXT[] matches
union all
select 'UK', ARRAY['United Kingdom' , 'Великобритания']::TEXT[]
union all
select 'US', array['USA', 'США']::text[]
)
update DataB
set
country_of_shipping = coalesce((select code from mapping where country_of_shipping = any(matches)),country_of_shipping),
consignee_country = coalesce((select code from mapping where consignee_country = any(matches)),consignee_country );
select * from DataB;
+-----------------+-------------------+
|consignee_country|country_of_shipping|
+-----------------+-------------------+
|US |US |
|RU |RU |
+-----------------+-------------------+