TimescaleDB/Postgres:插入冲突保持最大值

TimescaleDB/Postgres: INSERT ON CONFLICT KEEP MAXIMUM

我的 table 定义为:(这是一个简单的度量配置跟踪)

        CREATE TABLE IF NOT EXISTS strategy_registry (
        name            VARCHAR     NOT NULL,
        symbol          VARCHAR     NOT NULL,
        predictor_id    VARCHAR     NOT NULL,
        params          jsonb       NOT NULL,
        metric          FLOAT       NOT NULL,
        PRIMARY KEY(name, symbol, predictor_id)
        );

并且在插入冲突时,我想保留获得最大度量值的版本的最大度量和参数列。我正在使用 TimescaleDB (postgres 12)

    INSERT INTO strategy_registry (name, symbol, predictor_id, params, metric)
    VALUES ({{ name }}, {{ symbol }}, {{ predictor_id }}, {{ params }}, {{ metric }})
    ON CONFLICT (name, symbol, predictor_id) 
    DO UPDATE SET 
    (metric, params) = max(existing, excluded), params of greatest `metric` column value;

您要查找的函数是 greatest(...) 而不是 max。 Max 是一个柱状函数,适用于整个行集,在本例中为 table。 Greatest 从值(或变量)列表中选择 'maximum' 值。示例:

select greatest(1,4,3,5,7,0)

returns 7. 它也可以在作业中使用,如

something = greatest(...);

我认为您无法同时处理两列。这样的事情应该有效:

INSERT INTO strategy_registry (name, symbol, predictor_id, params, metric)
VALUES ({{ name }}, {{ symbol }}, {{ predictor_id }}, {{ params }}, {{ metric }})
  ON CONFLICT (name, symbol, predictor_id) 
    DO UPDATE 
      SET params = CASE 
                     WHEN metric < EXCLUDED.metric THEN EXCLUDED.params
                     ELSE params
                   END,
          metric = GREATEST(metric, EXCLUDED.metric);

我认为其他答案应该可行,但是,我想说这可能不是实现此目标的最有效方法。相反,我会在更新中使用 WHERE 子句:

ON CONFLICT (name, symbol, predictor_id)  DO UPDATE SET
metric = excluded.metric, params = excluded.params
WHERE excluded.metric > metric

即使值保持不变并导致 table 膨胀和额外的工作(另外,我认为它在语义上更清晰),先前的答案也可以进行更新。