Обновлять строки только когда соединение однозначно - PullRequest
0 голосов
/ 11 октября 2018

У меня есть две таблицы, a и b, обе с product_name и value.Столбец значения в a равен нулю.

Я бы хотел обновить таблицу a значениями из таблицы b.Из-за причуд в данных product_name не уникален ни в одной из таблиц.

Я хочу установить значение только тогда, когда между product_name есть одно однозначное совпадение.Если несколько строк в a имеют одно и то же имя продукта или более одной строки совпадают с b, я бы хотел оставить это значение пустым.Есть ли эффективный способ сделать это в Postgres?

Более простая версия этого кода - сначала идентифицировать уникальные названия продуктов в a.Затем обновите строки, в которых совпадает только одна строка в b, но я также не уверен, как записать это ограничение.

Ответы [ 3 ]

0 голосов
/ 11 октября 2018

Просто соедините [ Как выбрать каждую строку, где значение столбца НЕ ОТЛИЧНО и ответ @Gordon Linoff:

create table a (
     id serial primary key
    ,product_name text 
    ,value int
);

create table b (
     id serial primary key
    ,product_name text 
    ,value int not null
);

insert into a (product_name) values
   ('A')
   ,('B')
   ,('C')
   ,('D')
   ,('E')
   ,('E');


insert into b (product_name,value) values
    ('A',1)
   ,('A',1) 
   ,('B',42)
   ,('C',1)
   ,('C',2)
   ,('E',1)
;

update a
   set value = b.value
   from (select product_name, min(value) as value
         from b
         group by b.product_name
         having 1 = count(*)
        ) b
   where b.product_name = a.product_name
     and a.product_name not in
     (select product_name
        from a
        group by product_name
        having 1 < count(*));

@ Gordon Lindof Ваш ответ не удастся, если product_name и value обадублируется в b (пример product_name = A) и пропускает требование product_name, не дублированное в a.

0 голосов
/ 11 октября 2018

Простой способ:

update a
set value = (select min(b.value) from b where b.product_name = a.product_name)
where product_name in (select product_name from a group by product_name having count(*) = 1)
  and product_name in (select product_name from b group by product_name having count(*) = 1)
;
0 голосов
/ 11 октября 2018

Вы можете использовать агрегацию:

update a
   set value = b.value
   from (select b.product_name, max(b.value) as value
         from b
         group by b.product_name
         having min(b.value) = max(b.value)  -- there is only one value
        ) b
   where b.product_name = a.product_name;

Обратите внимание, что это предполагает, что b.value не null.Легко включить логику для null значений, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...