Уникальное ограничение в Postgres, основанное на последнем ненулевом значении - PullRequest
0 голосов
/ 12 октября 2018

У меня есть таблица, которая выглядит следующим образом: create table prices_history (id0 serial primary key, product_id0 int, time_added timestamptz, listed_price numeric)

Я хотел бы вставить новый price для определенного product_id0 в таблицу, когда max(time_added) этого product_id0 отличается от цены, которую я собираюсь вставить.В настоящее время я делаю это с помощью следующего запроса, предполагая, что я хочу вставить цену 9.50 для продукта с идентификатором 101:

  insert into prices_history (product_id0, time_added, price) 
  (
    select 101, NOW(), 9.50 where not exists (
      select * from (
        select distinct on (product_id0) * from prices_history order by product_id0, time_added desc
      ) x where product_id0=101 and listed_price=9.50
    )
  ) returning id0

. Есть ли лучший запрос для решения этой проблемы?проблема?

Я использую Postgres v9.6.8 в Ubuntu 16.04 LTS.

1 Ответ

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

Вместо использования WHERE NOT EXISTS я обнаружил, что более устойчивым решением для массовых вставок было LEFT JOIN..WHERE NULL.Это включает в себя левое соединение с данными, которые я хотел вставить, и выбор данных, для которых в старой таблице не было соответствующих данных.В следующем примере, скажем, у меня были следующие данные о ценах (представленные в JSON):

[{price: 11.99, product_id0:2},
 {price: 10.50, product_id0:3},
 {price: 10.00, product_id0:4}]

Следующий запрос вставил бы подмножество этих данных, если какая-либо из них будет новой информацией:

insert into prices_history (product_id0, time_added, price)
(
   select new_product_id0, new_time_added, new_price from
     (select unnest(array[11.99, 10.50, 10.00]) as new_price, unnest(array[2,3,4]) as new_product_id0, now() as new_time_added) new_prices left join
     (select distinct on (product_id0) * from prices_history order by product_id0, time_added desc) old_prices 
   on old_prices.product_id0 = new_prices.new_product_id0 and old_prices.listed_price= new_prices.new_price 
   where old_prices.product_id0 is null and old_prices.listed_price is null
) returning id0

Этот новый запрос, кажется, хорошо работает в текущем развертывании.

...