![](/img/trans.png)
[英]Insert data in one table, remove from another, with timestamp condition in mysql
[英]How to insert/update data from one table into another table (postgresql)?
有两张桌子
tmp_stat:
date, site_id, ip, block_id, count
Primary Key (date, site_id, ip, block_id)
main_stat:
date, site_id, ip, block_id, count
Primary Key (date, site_id, ip, block_id)
当没有这样的行(日期,site_id等)时,我需要从tmp_stat将行插入到main_stat中,并在它们已经存在时尽快更新计数
tmp_stat包含约500000行,main_stat包含millons
请问以下工作吗?
WITH upd AS (
UPDATE main_stat t
SET counter = s.counter
FROM tmp_stat s
WHERE t.date = s.date
AND t.site_id = s.site_id
AND t.ip = s.ip
AND t.block_id = s.block_id
RETURNING s.date, s.site_id, s.ip, s.block_id, s.counter
)
INSERT INTO main_stat
SELECT s.mydate, s.site_id, s.ip, s.block_id, s.counter
FROM tmp_stat s
LEFT JOIN upd ON (upd.date = s.date and upd.site_id = s.site_id and upd.ip = s.ip and upd.block_id = s.block_id)
WHERE upd.date IS NULL
;
更新:
看来这仅适用于9.1版或更高版本。
使用某人的WHERE (t.date, t.site_id, t.ip, t.block_id) = (s.date, s.site_id, s.ip, s.block_id)
建议WHERE (t.date, t.site_id, t.ip, t.block_id) = (s.date, s.site_id, s.ip, s.block_id)
似乎可以提供更好的性能。
WITH upd AS (
UPDATE main_stat t
SET counter = s.counter
FROM tmp_stat s
WHERE ( t.date, t.site_id, t.ip, t.block_id ) = ( s.date, s.site_id, s.ip, s.block_id )
RETURNING s.date, s.site_id, s.ip, s.block_id
)
INSERT INTO main_stat
SELECT s.date, s.site_id, s.ip, s.block_id, s.counter
FROM tmp_stat s
LEFT JOIN upd
ON ( upd.date = s.date
AND upd.site_id = s.site_id
AND upd.ip = s.ip
AND upd.block_id = s.block_id )
WHERE upd.date IS NULL
;
这里发生的是我们正在使用CTE进行UPDATE,而CTE返回已更新行的标识列。
然后,INSERT使用更新的行信息来过滤tmp_stat以仅插入新记录。
Dimitri Fontaine在此博客条目中涵盖了一些并发警告。
有关CTE的更多信息,请参见Postgresql 文档 。
据我所知,我正在基于gsimes的答案。
with agg_temp_stat as (
select date, site_id, ip, block_id, sum(counter)::integer counter
from temp_stat
group by 1, 2, 3, 4
), upd as (
update main_stat t
set counter = counter + s.counter
from agg_tmp_stat s
where
(t.date, t.site_id, t.ip, t.block_id)
= (s.date, s.site_id, s.ip, s.block_id)
returning s.date, s.site_id, s.ip, s.block_id
)
insert into main_stat
select s.date, s.site_id, s.ip, s.block_id, s.counter
from
agg_tmp_stat s
left join
upd on
upd.date = s.date
and upd.site_id = s.site_id
and upd.ip = s.ip
and upd.block_id = s.block_id
where upd.date is null
基本上汇总临时表,并将结果计数器加到已经存在的计数器上。
似乎很简单的Exists查询...如果对列进行了索引,它应该足够快。
例如:
-- insert missing rows
INSERT INTO main_stat (date, site_id, ip, block_id)
SELECT date, site_id, ip, block_id FROM tmp_stat tmp
WHERE NOT EXISTS (SELECT 1 FROM main_stats main
WHERE tmp.date = main.date
AND tmp.site_id = main.site_id
AND tmp.ip = main.ip
AND tmp.block_id = main.block_id
);
-- update count for existing rows
UPDATE main_stat main
SET count = main.count + (SELECT count FROM tmp_stats tmp
WHERE tmp.date = main.date
AND tmp.site_id = main.site_id
AND tmp.ip = main.ip
AND tmp.block_id = main.block_id
LIMIT 1)
WHERE EXISTS (SELECT 1 FROM main_stats main
WHERE tmp.date = main.date
AND tmp.site_id = main.site_id
AND tmp.ip = main.ip
AND tmp.block_id = main.block_id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.