2016-09-01 2 views
0

У меня есть набор данных, как следующее:Суммируя значения перед удалением избыточных записей

Identifier | Revenue | Good Inflow 
----------------------------------- 
    abc123 | 20 | 15 
    abc124 | 10 | 5 
    abc124 | 5 | 5 

Как вы можете видеть, что есть две строки с одинаковым идентификатором, различных доходов, но то же самое (резервированной) хороший приток. То, что я хочу достичь, - это исключить вторую строку с тем же идентификатором, но добавить доход в доход первой строки. Следовательно, результатом должно быть:

abc124 | 15 | 5 

Возможно ли это? Если так, какая команда мне нужна? Я использую Oracle SQL Developer.

Спасибо заранее!

Felix

+1

Пожалуйста, покажите свои данные в виде отформатированного текста, а не изображения. Это только три столбца в вашем столе? Вам нужно только объединить эту конкретную пару строк (что вы можете сделать с простым обновлением и удалить с использованием определенного значения), или у вас есть много одинаковых пар, которые нужно объединить? –

+0

Вы хотите, чтобы это было как запрос SELECT, так и как оператор удаления? – kbball

+0

@AlexPoole - Вопрос в том, действительно ли это требование (изменить данные в таблице, а не просто группировать данные для отчета) - это хорошая практика? На мой взгляд, в большинстве случаев это плохая практика. Можно писать представления (и MVs, если это необходимо для производительности) для целей анализа и отчетности, но базовые данные следует оставить в покое. – mathguy

ответ

0

Вы можете сделать это с помощью слияния. С фиктивной таблицей для моделирования ваших данных:

create table t42 (identifier varchar2(10), revenue number, good_inflow number); 
insert into t42 values ('abc123', 20, 15); 
insert into t42 values ('abc124', 10, 5); 
insert into t42 values ('abc124', 5, 5); 

вы можете использовать аналитические функции, чтобы получить в общей сложности в качестве дополнительного столбца с каждой строкой, а также ряд псевдо строк:

select t42.*, 
    sum(revenue) over (partition by identifier, good_inflow) as total_revenue, 
    row_number() over (partition by identifier, good_inflow order by rowid) as rn, 
    count(*) over (partition by identifier, good_inflow) as cnt 
from t42; 

IDENTIFIER REVENUE GOOD_INFLOW TOTAL_REVENUE RN CNT 
---------- ------- ----------- ------------- ---- ---- 
abc123   20   15   20 1 1 
abc124   10   5   15 1 2 
abc124   5   5   15 2 2 

Вы можете затем используйте это как предложение using инструкции merge, добавив rowid базовой таблицы в качестве условия on и используя сгенерированный cnt только для обновления тех, у которых есть дубликаты (так что любая пара ID/притока, которая появляется только один раз, не бесцельно обновляется до той же стоимости е):

merge into (select t42.*, rowid from t42) t42 
using (
    select t42.*, rowid, 
    sum(revenue) over (partition by identifier, good_inflow) as total_revenue, 
    row_number() over (partition by identifier, good_inflow order by rowid) as rn, 
    count(*) over (partition by identifier, good_inflow) as cnt 
    from t42 
) tmp 
on (tmp.rowid = t42.rowid and tmp.cnt > 1) 
when matched then 
    update set revenue = case when tmp.rn = 1 then tmp.total_revenue else null end 
delete where (revenue is null); 

2 rows merged. 

delete Предложение работ по значению после обновления; Я использовал выражение case для того, чтобы установить доход в null для всех, кроме номинальной первой строки для каждой комбинации. Теперь они могут быть удалены.

select * from t42; 

IDENTIFIER REVENUE GOOD_INFLOW 
---------- ------- ----------- 
abc123   20   15 
abc124   15   5 

Однако это не означает, что значение дохода не может быть равно нулю. Если он имеет значение NULL, он может быть адаптирован для решения этой проблемы.

Смежные вопросы