Как получить сумму уникальных элементов из текущей и предыдущей строк, но игнорировать повторяющиеся элементы Oracle SQL - PullRequest
0 голосов
/ 05 марта 2019

Как написать запрос в Oracle SQL , чтобы получить из таблицы, которую я имею, к таблице, которую я хочу, как показано ниже:

Что у меня есть:

Date            Item        Units
-----------     --------    --------
05-NOV-2018     A           3
05-NOV-2018     E           4
09-NOV-2018     C           7
16-NOV-2018     B           9
16-NOV-2018     D           4
21-NOV-2018     A           5
29-NOV-2018     B           12
29-NOV-2018     C           10
29-NOV-2018     F           6
29-NOV-2018     A           8

Что я хочу:

Date            Total_Units_Per_Day
-----------     --------------------
05-NOV-2018     7
09-NOV-2018     14
16-NOV-2018     27
21-NOV-2018     29
29-NOV-2018     44

Как был рассчитан столбец Total_Units_Per_Day:

Date            Item        Units       Total_Unique_Items_Accumulated_Per_Day      Total_Units_Per_Day
-----------     --------    --------    -------------------------------             --------------------
05-NOV-2018     A           3           A, E                                        7
05-NOV-2018     E           4           A, E                                        7
09-NOV-2018     C           7           A, E, C                                     14
16-NOV-2018     B           9           A, E, C, B, D                               27
16-NOV-2018     D           4           A, E, C, B, D                               27
21-NOV-2018     A           5           A, E, C, B, D                               29
29-NOV-2018     B           12          A, E, C, B, D, F                            44
29-NOV-2018     C           10          A, E, C, B, D, F                            44
29-NOV-2018     F           6           A, E, C, B, D, F                            44
29-NOV-2018     A           8           A, E, C, B, D, F                            44

По мере прохождения каждого дня (с 5 по 29 ноября 2018 года), суммируйте единицы для каждогопункт в этот день и весь предыдущий день. Однако , не учитывайте единицы товара за предыдущий (ые) день, если он уже присутствует в текущем дне.

Например, 21 ноября 2018 года, Total_Units_Per_Day = 29 .Это делается путем суммирования единиц всех предыдущих элементов , но использования:

A = 5 единиц с (21 ноября 2018 года) вместо A = 3 единицы с (5 ноября)2018)

Возможен ли этот тип запроса?Любая помощь будет оценена (: Спасибо!

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Это был бы классический подход к решению вашей проблемы: просто сложите единицы в день, а затем вычислите кумулятивную сумму, используя аналитическую функцию.

with tot as (
select trans_date, sum(units) total_unit 
from tab
group by trans_date)
select trans_date, 
sum(total_unit) over (order by trans_date) total_unit_cum
from tot
order by 1 
;

TRANS_DATE          TOTAL_UNIT_CUM
------------------- --------------
05.11.2018 00:00:00              7
09.11.2018 00:00:00             14
16.11.2018 00:00:00             27
21.11.2018 00:00:00             32
29.11.2018 00:00:00             68

Но это обеспечивает более высокие ожидаемые результаты.Причина в том, что в пределах item ваши units уже накоплены.

Итак, на первом шаге очистите единицы и вычислите реальное значение дельты вычитая значение LAG - из предыдущей записи, с нулем по умолчанию - lag(units,1,0) ...

select 
trans_date, item, units units_orig,
units - lag(units,1,0) over (partition by item order by trans_date) units
from tab
order by 1,2;

TRANS_DATE          I UNITS_ORIG       UNITS
------------------- - ---------- ----------
05.11.2018 00:00:00 A          3          3
05.11.2018 00:00:00 E          4          4
09.11.2018 00:00:00 C          7          7
16.11.2018 00:00:00 B          9          9
16.11.2018 00:00:00 D          4          4
21.11.2018 00:00:00 A          5          2
29.11.2018 00:00:00 A          8          3
29.11.2018 00:00:00 B         12          3
29.11.2018 00:00:00 C         10          3
29.11.2018 00:00:00 F          6          6

Окончательно просто объедините оба запроса

with clean as (
select 
trans_date, item, units units_orig,
units - lag(units,1,0) over (partition by item order by trans_date) units
from tab),
tot as (
select trans_date, sum(units) total_unit 
from clean
group by trans_date)
select trans_date, 
sum(total_unit) over (order by trans_date) total_unit_cum
from tot
order by 1 
;

TRANS_DATE          TOTAL_UNIT_CUM
------------------- --------------
05.11.2018 00:00:00              7
09.11.2018 00:00:00             14
16.11.2018 00:00:00             27
21.11.2018 00:00:00             29
29.11.2018 00:00:00             44

Это не закороченный возможный запрос, но просто понять ...

0 голосов
/ 05 марта 2019

Это довольно сложно.Похоже, вам нужно самое последнее значение для каждого элемента.

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

select dte, 
       (lag(case when item = 'A' then units end ignore nulls, 1, 0) over (order by dte) +
        lag(case when item = 'B' then units end ignore nulls, 1, 0) over (order by dte) +
        lag(case when item = 'C' then units end ignore nulls, 1, 0) over (order by dte) +
        lag(case when item = 'D' then units end ignore nulls, 1, 0) over (order by dte) +
        lag(case when item = 'E' then units end ignore nulls, 1, 0) over (order by dte) +
        lag(case when item = 'F' then units end ignore nulls, 1, 0) over (order by dte) 
       ) as total_units_per_day
from t;

Здесь - это дБ <> скрипка.

РЕДАКТИРОВАТЬ:

Вот более общий подход:

select dte, sum(units) as total_units_per_day
from (select d.dte, t.item, t.units, row_number() over (partition by t.item, d.dte order by t.dte desc) as seqnum
      from (select distinct dte from t) d join
           t
           on t.dte <= d.dte
    ) td 
where seqnum = 1
group by dte
order by dte;

И дБ <> скрипка для этого.

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