我想根据UPDATE
表数据client
维度表event
中的某些列:
UPDATE client AS c
SET
some_attr_last_value = last_attr_values.value
FROM (
SELECT
l.client_id,
value,
ROW_NUMBER() OVER (PARTITION BY l.client_id ORDER BY timestamp DESC) AS num
FROM event AS l
WHERE
timestamp > DATE_TRUNC('month', NOW() - INTERVAL '1 month')
) AS last_attr_values
WHERE
last_attr_values.num = 1 AND
c.client_id = last_attr_values.client_id AND
c.some_attr_last_value <> last_attr_values.value;
我已经有了一些像上面这样的查询:它们以相同的方式更新其他列(仅与其他列一起)并且运行良好。但是一个查询会产生错误:
错误6745:重复键值:'client_id = ...' - 违反约束'... .client.C_PRIMARY'
但我不会尝试更改client_id
。为什么会出现这个错误?
我检查client
表,但它没有重复。 ANALYZE_CONSTRAINTS('client')
也不会返回任何违规行为。
版本是7.2.2-1。
答案 0 :(得分:3)
问题不在于您的客户表,而是内部选择。
SELECT
l.client_id,
value,
ROW_NUMBER() OVER (PARTITION BY l.client_id ORDER BY timestamp DESC) AS num
FROM event AS l
WHERE
timestamp > DATE_TRUNC('month', NOW() - INTERVAL '1 month')
SELECT中有什么可以确保每个客户端有一条记录?
假设您有多个客户有多个事件的事件。
因为您的窗口函数按时间戳排序
ROW_NUMBER() OVER (PARTITION BY l.client_id ORDER BY timestamp DESC) AS num
你会得到
我认为您需要在ORDER BY中包含Client_id才能使查询生效。
更新:一段时间后,错误再次发生。我试图使用上面的解决方案,但不幸的是它没有帮助。仅使用临时表克服了错误:
CREATE LOCAL TEMPORARY TABLE last_values ON COMMIT PRESERVE ROWS
AS SELECT client_id, value FROM (
SELECT
l.client_id,
value,
ROW_NUMBER() OVER (PARTITION BY l.client_id ORDER BY timestamp DESC) AS num
FROM event AS l WHERE timestamp > DATE_TRUNC('month', NOW() - INTERVAL '1 month')
) last_values WHERE last_values.num = 1;
UPDATE client AS c
SET some_attr_last_value = last_values.value
FROM last_values
WHERE c.client_id = last_values.client_id AND c.some_attr_last_value <> last_attr_values.value
DROP TABLE last_values;
所以虽然问题解决了,但我没有找到确切的原因。