我有一个数据库表,我需要在其上运行UPDATE语句。该表有大约250,000条记录,因此优化的性能很重要。
以下是相关的数据库架构和一些示例数据。
audit_logs -- id -- ticket_id -- ip_address -- created_at -- -- 10 -- 100 -- 100.101.102.103 -- 2014-08-22 11:17:28.325844 -- -- 11 -- 100 -- 100.101.102.103 -- 2014-08-23 12:18:28.325844 -- -- 12 -- 101 -- 200.1.2.3 -- 2014-08-24 13:19:28.325844 -- -- 13 -- 101 -- 201.2.3.4 -- 2014-08-25 14:20:28.325844 -- -- 14 - 101 -- 202.3.4.5 -- 2014-08-26 15:21:28.325844 -- -- 15 - 102 -- 102.12.34.56 -- 2014-08-27 16:22:28.325844 --
这是我需要做的。对于具有多于1个IP地址的记录的任何ticket_id,我需要为除第一个以外的每个IP地址将ticket_id设置为NULL。以下是上述数据的示例结果。
audit_logs -- id -- ticket_id -- ip_address -- created_at -- -- 10 -- 100 -- 100.101.102.103 -- 2014-08-22 11:17:28.325844 -- -- 11 -- 100 -- 100.101.102.103 -- 2014-08-23 12:18:28.325844 -- -- 12 -- 101 -- 200.1.2.3 -- 2014-08-24 13:19:28.325844 -- -- 13 -- NULL -- 201.2.3.4 -- 2014-08-25 14:20:28.325844 -- -- 14 - NULL -- 202.3.4.5 -- 2014-08-26 15:21:28.325844 -- -- 15 - 102 -- 102.12.34.56 -- 2014-08-27 16:22:28.325844 --
因此,可以有多个具有相同票证的记录。但是,如果有一个以上的IP地址与一个票证相关联,那么每个记录的IP地址都不是第一个看到的IP地址。
我使用的实际RDBMS是Postgres。最简单的方法是什么?谢谢大家。
答案 0 :(得分:1)
不幸的是Postgres还不支持count(distinct ..)
作为窗口函数,所以它比必要的复杂一点:
update audit_logs
set ticket_id = null
from (
select a.id,
a.ticket_id,
row_number() over (partition by a.ticket_id order by a.created_at) as rn
from audit_logs a
join (
select ticket_id
from audit_logs
group by ticket_id
having count(distinct ip_address) > 1
) t on t.ticket_id = a.ticket_id
) x
where x.id = audit_logs.id
and x.rn > 1;
SQLFiddle:http://sqlfiddle.com/#!15/a632c/1
最里面的选择(别名t
)获得具有多个IP地址的所有ticket_id
。然后将其与基表连接以计算行数。然后在update
中使用该结果来查找应更新的行。
不确定性能,它在很大程度上取决于最内部选择将返回的行数。
答案 1 :(得分:0)
尝试这样的事情开始,稍后进行优化
UPDATE audit_logs O
SET ticket_id = NULL
WHERE (
SELECT count(distinct ip_address)
FROM audit_logs I WHERE I.ticket_id = O.ticket_id
) > 1 AND id <> (
SELECT DISTINCT ON (id) id
FROM audit_logs I WHERE I.ticket_id = O.ticket_id
) AND ip_address <> (
SELECT DISTINCT ON (ip_address) ip_address
FROM audit_logs I WHERE I.ticket_id = O.ticket_id
)
P.S。我的PostgreSQL很生疏,所以语法可能有些偏差......我的家用机器上安装了PostgreSQL来检查,对不起。