Объединить две таблицы с одинаковыми именами столбцов, добавить счетчики - PullRequest
6 голосов
/ 02 марта 2011

У меня две таблицы с одинаковыми столбцами, первый столбец - это имя, а второй - счетчик. Я хотел бы объединить эти таблицы, чтобы каждое имя отображалось с добавленным счетчиком двух таблиц:

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 - тест1, а Таблица2 - тест2):

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: /919371/vstavit-pri-povtornom-obnovlenii-v-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;

Ответы [ 3 ]

12 голосов
/ 02 марта 2011
=> 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)
8 голосов
/ 02 марта 2011

Как насчет этого, в чистом 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 нет, объединение даст нам NULL для t2.name и t2.name.

Функция COALESCE возвращает первый ненулевой аргумент, поэтому мы используем его для «преобразования» отсчетов NULL в 0 и выбора имени из правильной таблицы. Спасибо за отзыв на этот Уэйн!

Удачи!

0 голосов
/ 19 февраля 2014

Альтернативным методом является использование 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» появляются в промежуточном результате дважды. Чтобы объединить эти повторяющиеся строки и суммировать счетчики, мы можем сгруппировать строки по столбцу имени и суммировать столбец счета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...