【问题标题】:Unique constraint in Postgres based on last non-null valuePostgres中基于最后一个非空值的唯一约束
【发布时间】:2019-03-17 06:44:51
【问题描述】:

我有一个如下所示的表格:create table prices_history (id0 serial primary key, product_id0 int, time_added timestamptz, listed_price numeric)

max(time_added) 中的product_id0 与我将要插入的价格不同时,我只想为特定product_id0 插入一个新的price 到表中。目前,我正在通过以下查询执行此操作,假设我想为 id 为101 的产品插入价格9.50

  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

有没有更好的查询来解决这个问题?

我在 Ubuntu 16.04 LTS 上使用 Postgres v9.6.8

【问题讨论】:

  • to 2):索引不是过滤器。如果需要,最好制定一个可以为您提供当前价格的查询,并为此查询创建一个(物化)视图。之后,您应该使用 EXPLAIN 分析您的查询并使用适当的索引优化其性能。
  • 如果您想避免创建重复的 productid/price/date 那么为什么不创建一个唯一的约束呢?另外,为什么存在子句中的嵌套查询?它对你无能为力。但我认为无论如何都没有窗口。其他人可能肯定会回答这个问题。
  • @clemens 为这个查询创建物化视图有什么好处?我怎么能在当前的上下文中使用它?
  • 物化视图是永久存储其内容的视图,您可以在其上创建索引。如果您正确使用它们,您可以极大地加快复杂查询的速度。但是,它们通常只对很少更改的表有用。
  • @clemens 我希望经常插入到这个表中。

标签: sql postgresql database-design concurrency constraints


【解决方案1】:

我发现不是使用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

这个新查询似乎在当前部署中运行良好。

【讨论】:

    猜你喜欢
    • 2015-03-06
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多