обновление записей путем ввода значения суммы (столбца)

#sql #oracle12c

#sql #oracle12c

Вопрос:

У меня есть таблица 1, подобная этой:

  ----- ----- ------ 
| cat | val | type |
 ----- ----- ------ 
| A   | 100 | c1   |
| H   | 25  | c2   |
| H   | 50  | c3   |
| H   | 30  | c2   |
| A   | 15  | c3   |
| H   | 10  | c1   |
| H   | 15  | c1   |
| B   | 10  | c4   |
| H   | 20  | c4   |
| H   | 15  | c3   |
 ----- ----- ------ 
  

Мне нужно добавить группу sum (val) по типу только к одному H, принадлежащему каждому типу

Итак, у меня есть после группировки по типу, скажем, table2 :

  ----- ----- 
| cat | val |
 ----- ----- 
| c1  | 125 |
| c2  | 55  |
| c3  | 80  |
| c4  | 30  |
 ----- ----- 
  

Мне нужно добавить 125 к любому из H значений с типом c1, 55 к любому из H значений с c2 и так далее..Если в c1 нет H, то он должен создать эту запись.

Итак, наконец, мы получаем:

      ----- ----- ------ 
    | cat | val | type |
     ----- ----- ------ 
    | A   | 100 | c1   |
    | H   | 25  | c2   |
    | H   | 130 | c3   |
    | H   | 85  | c2   |
    | A   | 15  | c3   |
    | H   | 135 | c1   |
    | H   | 15  | c1   |
    | B   | 10  | c4   |
    | H   | 50  | c4   |
    | H   | 15  | c3   |
     ----- ----- ------ 
  

Как мне это сделать, не выполняя группировку table1 union table2 (с ‘H’ в качестве cat) по типу? Также у меня нет прав на обновление и я не могу использовать хранимые процедуры. Я также должен иметь в виду, что table1 является результатом запроса, включающего несколько внутренних объединений, которые я не хочу использовать снова и снова для операторов select.

Комментарии:

1. Почему строка | H | 25 | c2 | вообще не меняется? То же самое для | H | 15 | c1 | и | H | 15 | c3 | ?

2. @MatBailie потому что необходимо обновить любую комбинацию (H, Cs) и не более того

Ответ №1:

Посмотрите, имеет ли это смысл. Я добавил столбец ID просто для отображения конечного результата в том же порядке, что и входные данные (для облегчения чтения).

 SQL> -- T1 is what you currently have; it can/could be your current query
SQL> with t1 (id, cat, val, type) as
  2    (select 1, 'A', 100, 'C1' from dual union all
  3     select 2, 'H', 25 , 'C2' from dual union all
  4     select 3, 'H', 50 , 'C3' from dual union all
  5     select 4, 'H', 30 , 'C2' from dual union all
  6     select 5, 'A', 15 , 'C3' from dual union all
  7     select 6, 'H', 10 , 'C1' from dual union all
  8     select 7, 'H', 15 , 'C1' from dual union all
  9     select 8, 'B', 10 , 'C4' from dual union all
 10     select 9, 'H', 20 , 'C4' from dual union all
 11     select 10,'H', 15 , 'C3' from dual
 12    ),
 13  -- sum VAL per type
 14  t1_sum as
 15    (select type, sum(val) sum_val
 16     from t1
 17     group by type
 18    ),
 19  -- find row number; let any H be number 1
 20  t1_rn as
 21    (select id, cat, val, type,
 22       row_number() over (partition by type
 23                          order by case when cat = 'H' then 1 end) rn
 24     from t1
 25    )
 26  -- the final resu< add SUM_VAL to the first H row per type
 27  select r.cat, r.val   case when r.rn = 1 then s.sum_val else 0 end val,
 28    r.type
 29  From t1_rn r join t1_sum s on s.type = r.type
 30  order by r.id;

CAT        VAL TYPE
--- ---------- ----
A          100 C1
H           80 C2
H          130 C3
H           30 C2
A           15 C3
H          135 C1
H           15 C1
B           10 C4
H           50 C4
H           15 C3

10 rows selected.

SQL>
  

[РЕДАКТИРОВАТЬ: пытаюсь прояснить, как использовать ваш большой запрос]

Предположим, что это ваш очень большой и сложный запрос:

 select a.cat, 
       case when a.cat = 'A' then b.val 
            when a.cat = 'Z' then c.val
            else 'H'
       end val,
       c.type
from a join b on a.id = b.id and a.x = b.y
       join c on c.id = b.idx
where a.date_column < sysdate
  and c.type = 'X';
  

Как я уже сказал, создайте представление на его основе в виде

 create or replace view v_view as
select a.cat, 
       case when a.cat = 'A' then b.val 
            when a.cat = 'Z' then c.val
            else 'H'
       end val,
       c.type
from a join b on a.id = b.id and a.x = b.y
       join c on c.id = b.idx
where a.date_column < sysdate
  and c.type = 'X';
  

и использовать его в качестве источника для «моего» запроса (начиная со строки 14 и далее):

 with t1_sum as
  (select type, sum(val) sum_val
   from v_view                      --> here's the view
   group by type
  ), etc.
  

Или используйте сам «огромный» запрос в качестве начального CTE:

 with t1 as
-- this is your "huge" query
(select a.cat,  
       case when a.cat = 'A' then b.val 
            when a.cat = 'Z' then c.val
            else 'H'
       end val,
       c.type
from a join b on a.id = b.id and a.x = b.y
       join c on c.id = b.idx
where a.date_column < sysdate
  and c.type = 'X'
),
-- sum VAL per type
t1_sum as
  (select type, sum(val) sum_val
   from t1
   group by type
  ), etc.
  

Комментарии:

1. Но как это сделать, если количество записей в table1 очень велико? В реальном сценарии у меня было бы около 5 миллионов записей в таблице. Я, конечно, не могу выбрать использование ID индивидуально

2. А также я хочу использовать t1 только один раз, поскольку он имеет несколько внутренних объединений и множество операторов case, что делает запрос очень громоздким при использовании более одного раза.

3. Ваш «большой запрос с несколькими внутренними объединениями и множеством операторов case» был бы моим T1 CTE. Если вам неприятно это видеть, создайте представление на основе этого запроса. Кто что-нибудь говорил о выборе отдельных идентификаторов? Если вы имеете в виду столбец «мой идентификатор», то перечитайте еще раз, что я сказал об этом. Наконец, у меня нет никаких возражений, если вы напишете свой собственный код (или подождете немного дольше или неопределенно долго, пока кто-нибудь другой опубликует другой вариант). Вкратце: примите это или оставьте.

4. Безусловно, «возьму это» всего с несколькими разъяснениями -1. как мне написать инструкции «выберите 1, ‘A’, 100, ‘C1’ из двойного объединения all …» для всех строк, которые у меня есть в моей таблице, и 2. Если я использую сложное представление, смогу ли я выполнить дальнейшую группировку по нему? В любом случае спасибо, что приложили усилия для ответа

5. Я отредактировал свое сообщение и добавил еще немного кода, который, надеюсь, показывает, что я имел в виду. Взгляните, пожалуйста. Имеет ли это теперь больше смысла?