【问题标题】:PostgreSQL Upsert For Almost Similar ValuesPostgreSQL Upsert 用于几乎相似的值
【发布时间】:2021-05-03 21:40:54
【问题描述】:

我正在尝试将相似值 (val1,val2) 的命中计数保持在指定阈值(±某个值)内。
对于完全匹配,我会使用 UPSERT,但我不知道如何使它适用于类似的匹配。

给定一张桌子valuetable

id val1 val2 count
1 1.1 2.2 2
2 1.7 2.2 1
3 1.0 2.2 1

我们应该这样做

INSERT INTO valuetable 
VALUES(DEFAULT, 1.2, 2.1, 1) 
ON CONFLICT (val1 ± 0.1,val2 ± 0.1)
DO 
  UPDATE SET count = count + 1

我们将得到下表,其中id=1count 递增,因为val1val2id=1 在指定的0.1 范围内。

id val1 val2 count
1 1.1 2.2 3
2 1.7 2.2 1
3 1.0 2.2 1

如果可能的话,还有另一个问题。 如果我们要进行下面的查询,id=1id=3 都符合条件。

INSERT INTO valuetable 
VALUES(DEFAULT, 1.0, 2.1, 1) 
ON CONFLICT (val1 ± 0.1,val2 ± 0.1)
DO 
  UPDATE SET count = count + 1

我们如何更新具有最高(或最低)count 的那个(例如,id=1 得到更新,因为它在所有匹配行中具有最高的 count,共 2 个)?

id val1 val2 count
1 1.1 2.2 3
2 1.7 2.2 1
3 1.0 2.2 1

更新净差最小(或最大)的那个(例如 id=3 得到更新,因为它的净差为 0.1 而不是 id=1 0.2)?

id val1 val2 count
1 1.1 2.2 2
2 1.7 2.2 1
3 1.0 2.2 2

注意:有过标准化值的想法,例如0.1, 0.2, ...,因此可以进行精确匹配, 但最好不要诉诸于此,因为0.1, 0.2, ... 的阈值为0.5 仍然会遇到同样的问题,而0.5, 1.0, ... 会丢失太多上下文。

【问题讨论】:

    标签: sql postgresql insert-update postgresql-9.5 upsert


    【解决方案1】:

    您需要使用显式逻辑来执行此操作,而不是 upsert。我可能会建议一个两步流程:

    with v as (
          select t.*
          from (values (1.2, 2.1)) v(val1, val2)
         ),
         i as (
          insert into valuetable (val1, val2, count)
              select val1, val2, 0
              from v
              where not exists (select 1
                                from valuetable vt
                                where abs(vt.val1 - v.val1) < 0.1 and
                                      abs(vt.val2 - v.val2) < 0.1
                               )
              returning *
         )
    update valuetable vt
        set count = count + 1
        from v
        where abs(vt.val1 - v.val1) < 0.1 and
              abs(vt.val2 - v.val2) < 0.1;
    

    这会插入计数为“1”的值,然后增加匹配行的值。这不是最有效的方法,但解释起来很简单。

    另一种方法是对数据进行规范化,使值沿每个维度以 0.2 为增量 - 并为此创建一个唯一维度。然后你可以使用 upsert:

    create unique index unq_t_val1_val2
        on (floor(val1 * 5), floor(val2 * 5));
    

    然后你可以在你的问题中使用upsert。但是,不要在(val1, val2) 上单独创建唯一索引,因为两者会发生冲突。

    【讨论】:

    • 谢谢,决定是选择一个舒适的增量,但很巧合。
    猜你喜欢
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    相关资源
    最近更新 更多