#sql #oracle #for-loop #plsql
#sql #Oracle #for-цикл #plsql
Вопрос:
У меня есть таблица, которая выглядит следующим образом:
Pam_A Week Value_1
A 1 10
A 2 13
B 3 15
B 4 10
B 5 11
B 6 10
Я хочу добиться следующего:
Pam_A Week Value_1 Value_2
A 1 10
A 2 13
B 3 15 28
B 4 10 38
B 5 11 49
B 6 10 59
Когда Pam_A=B, суммируйте текущее Значение_1 и его предыдущее значение в строке и продолжайте увеличивать это значение в соответствии со следующим значением в Значении_1
Есть идеи для достижения этой совокупной суммы?
Ответ №1:
Прежде всего, вам нужно отметить все строки, которые вы хотите посчитать. Вы можете сделать это следующим образом:
with t(Pam_A, Week, Value_1) as (
select 'A', 1, 10 from dual union all
select 'A', 2, 13 from dual union all
select 'B', 3, 15 from dual union all
select 'B', 4, 10 from dual union all
select 'B', 5, 11 from dual union all
select 'B', 6, 10 from dual
)
select
Pam_A, Week, Value_1
,case
when Pam_A='B' or lead(Pam_A)over(order by week) = 'B'
then 'Y'
else 'N'
end as flag
from t;
Результаты:
PAM_A WEEK VALUE_1 FLAG
----- ---------- ---------- ----
A 1 10 N
A 2 13 Y
B 3 15 Y
B 4 10 Y
B 5 11 Y
B 6 10 Y
6 rows selected.
Затем вы можете агрегировать только те строки, которые имеют flag =’Y’:
with t(Pam_A, Week, Value_1) as (
select 'A', 1, 10 from dual union all
select 'A', 2, 13 from dual union all
select 'B', 3, 15 from dual union all
select 'B', 4, 10 from dual union all
select 'B', 5, 11 from dual union all
select 'B', 6, 10 from dual
)
select
v.*
,case
when flag='Y' and Pam_a='B'
then sum(Value_1)over(partition by flag order by Week)
end as sums
from (
select
Pam_A, Week, Value_1
,case
when Pam_A='B' or lead(Pam_A)over(order by week) = 'B'
then 'Y'
else 'N'
end as flag
from t
) v;
Результаты:
PAM_A WEEK VALUE_1 FLAG SUMS
----- ---------- ---------- ---- ----------
A 1 10 N
A 2 13 Y
B 3 15 Y 28
B 4 10 Y 38
B 5 11 Y 49
B 6 10 Y 59
6 rows selected.
Ответ №2:
Используя комбинацию LEAD
SUM
аналитических функций и, вы можете определить, в каких строках следующий PAM_A имеет значение B, только SUM
если следующая строка — B или текущая строка — B.
Запрос
WITH
d (pam_a, week, value_1)
AS
(SELECT 'A', 1, 10 FROM DUAL
UNION ALL
SELECT 'A', 2, 13 FROM DUAL
UNION ALL
SELECT 'B', 3, 15 FROM DUAL
UNION ALL
SELECT 'B', 4, 10 FROM DUAL
UNION ALL
SELECT 'B', 5, 11 FROM DUAL
UNION ALL
SELECT 'B', 6, 10 FROM DUAL)
SELECT pam_a,
week,
value_1,
CASE
WHEN pam_a = 'B'
THEN
SUM (CASE WHEN next_pam_a = 'B' OR pam_a = 'B' THEN value_1 ELSE 0 END)
OVER (ORDER BY week)
ELSE
NULL
END value_2
FROM (SELECT pam_a, week, value_1, LEAD (pam_a) OVER (ORDER BY week) AS next_pam_a FROM d);
Результат
PAM_A WEEK VALUE_1 VALUE_2
________ _______ __________ __________
A 1 10
A 2 13
B 3 15 28
B 4 10 38
B 5 11 49
B 6 10 59
Ответ №3:
Если я понимаю, вам нужна совокупная сумма, но с условностью:
select t.*,
(case when pam_A = 'B' then sum(value_1) over (order by week) end) as value_2
from t;