我有两个具有相同列的表,第一列是名称,第二列是计数。我想合并这些表,以便每个名称都显示两个表的添加计数:
Table1: Table2: Result Table:
NAME COUNT NAME COUNT NAME COUNT
name1 1 name3 3 name1 1
name2 2 name4 4 name2 2
name3 3 name5 5 name3 6
name4 4 name6 6 name4 8
name5 5
name6 6
到目前为止,我已经创建了一个非常丑陋的结构来执行此操作,并且想知道是否有可能以更优雅的方式获得结果。
到目前为止(表1是test1,表2是test2):
create table test1 ( name varchar(40), count integer);
create table test2 ( name varchar(40), count integer);
create table test3 ( name varchar(40), count integer);
create table test4 ( name varchar(40), count integer);
create table test5 ( name varchar(40), count integer);
insert into test4 (name, count) select * from test1;
insert into test4 (name, count) select * from test2;
insert into test3 (name , count) select t1.name, t1.count + t2.count
from test1 t1 inner join test2 t2 on t1.name = t2.name;
select merge_db(name, count) from test3;
insert into test5 (name, count) (select name, max(count) from test4 group by name);
CREATE FUNCTION merge_db(key varchar(40), data integer) RETURNS VOID AS
$$ -- souce: http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-postgresql
BEGIN
LOOP
-- first try to update the key
UPDATE test4 SET count = data WHERE name = key;
IF found THEN
RETURN;
END IF;-- not there, so try to insert the key -- if someone else inserts the same key concurrently, -- we could get a unique-key failure
BEGIN
INSERT INTO test4(name,count) VALUES (key, data);
RETURN;
EXCEPTION WHEN unique_violation THEN-- do nothing, and loop to try the UPDATE again
END;
END LOOP;
END;
$$
LANGUAGE plpgsql;
答案 0 :(得分:12)
=> create table t1 (name text,cnt int);
=> create table t2 (name text,cnt int);
=> insert into t1 values ('name1',1), ('name2',2), ('name3',3), ('name4',4);
=> insert into t2 values ('name3',3), ('name4',4), ('name5',5), ('name6',6);
=>
select name,sum(cnt) from
(select * from t1
union all
select * from t2 ) X
group by name
order by 1;
name | sum
-------+-----
name1 | 1
name2 | 2
name3 | 6
name4 | 8
name5 | 5
name6 | 6
(6 rows)
答案 1 :(得分:8)
在纯SQL中如何:
SELECT
COALESCE(t1.name, t2.name),
COALESCE(t1.count, 0) + COALESCE(t2.count, 0) AS count
FROM t1 FULL OUTER JOIN t2 ON t1.name=t2.name;
基本上我们在名称字段上进行完全外连接以合并两个表。棘手的部分是,使用完整的外连接,将出现在一个表中但不存在另一个表中的行,但在另一个表中将具有NULL;因此,如果t1具有“name1”但t2没有,则连接将为t2.name和t2.name提供NULL。
COALESCE函数返回第一个非NULL参数,因此我们使用它将NULL计数“转换”为0并从正确的表中选择名称。感谢您对Wayne的提示!
祝你好运!答案 2 :(得分:0)
另一种方法是使用NATURAL FULL OUTER JOIN结合SUM(count)和GROUP BY name语句。以下SQL代码完全产生了所需的结果:
SELECT name, SUM(count) AS count FROM
( SELECT 1 AS tableid, * FROM t1 ) AS table1
NATURAL FULL OUTER JOIN
( SELECT 2 AS tableid, * FROM t2 ) AS table2
GROUP BY name ORDER BY name
人工 tableid 列确保NATURAL FULL OUTER JOIN为t1中的每一行和t2中的每一行创建一个单独的行。换句话说,行“name3,3”和“name4,4”在中间结果中出现两次。为了合并这些重复行并对计数求和,我们可以按名称列对行进行分组,并将计数列相加。