Группировка / агрегирование диапазонов данных по строкам в SQL - PullRequest
0 голосов
/ 11 октября 2019

У меня есть следующая таблица владения продуктом с диапазонами дат:

enter image description here

Можно найти DDL для таблицы ввода ЗДЕСЬ .

Каждый товар может принадлежать только одной группе. Клиент не может иметь два экземпляра одного и того же продукта в любой момент времени.

Мы можем визуализировать сроки владения продуктом, указанные выше:

timeline of product ownership

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

output 1

Наконец,общее количество продуктов, принадлежащих клиенту, и количество групп, к которым принадлежат эти продукты:

enter image description here

Это в Oracle, но было бы здорово иметь кодв ANSI SQL.

Есть подсказки?

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Вы можете получить совокупное количество продуктов, повернув даты в столбец, чтобы отслеживать входящие и исходящие значения. Затем кумулятивная сумма получает количество продуктов.

Получение количества групп является более сложной задачей. Следующее использует подзапрос:

with dtes as (
      select customer_id, date_from as dte, 1 as inc
      from t
      union all
      select customer_id, date_to + 1, -1 as inc
      from t
     )
select customer_id, dte as date_from,
       lead(dte) over (partition by customer_id order by dte) - 1 as date_to,
       sum(sum(inc)) over (partition by customer_id order by dte),
       (select count(distinct t2.prd_grp_id)
        from t t2
        where dtes.customer_id = t2.customer_id and
              dtes.dte between t2.date_from and t2.date_to
       ) as num_groups
from dtes
group by customer_id, dte
order by customer_id, dte;

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

0 голосов
/ 11 октября 2019

Рабочий раствор

ВЫХОД № 1

with dtes as (
      select customer_id, prd_grp_id, date_from as dte, 1 as inc
      from t
      union all
      select customer_id, prd_grp_id, date_to + 1, -1 as inc
      from t
     ),
grps as (
select customer_id, prd_grp_id, dte as date_from,
       lead(dte) over (partition by customer_id, prd_grp_id order by dte) - 1 as date_to,
       sum(sum(inc)) over (partition by customer_id, prd_grp_id order by dte) as n_prods
from dtes
group by customer_id, prd_grp_id, dte
)
select * from grps where n_prods>0;

ВЫХОД № 2

with dtes as (
      select customer_id, date_from as dte, 1 as inc
      from t
      union all
      select customer_id, date_to + 1, -1 as inc
      from t
     ),
totals as (
select customer_id, dte as date_from,
       lead(dte) over (partition by customer_id order by dte) - 1 as date_to,
       sum(sum(inc)) over (partition by customer_id order by dte) as num_prods,
       (select count(distinct t2.prd_grp_id)
        from t t2
        where dtes.customer_id = t2.customer_id and
              dtes.dte between t2.date_from and t2.date_to
       ) as num_groups
from dtes
group by customer_id, dte )
select * from totals where num_groups>0 order by customer_id, date_from;

Скрипка здесь

Спасибо @ Гордон Линофф !

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