Как рассчитать фактическое число для каждого дня, используя даты начала и окончания? - PullRequest
1 голос
/ 01 апреля 2019

Мне нужно рассчитать количество отдельных ID для каждой даты.Есть ли способ сделать это только с SQL, без использования PL / SQL?

create table test (
    id number(10),
    start_date timestamp,
    end_date timestamp
);

insert into test values(1, to_date('01.01.2019', 'dd.mm.yyyy'),  to_date('03.01.2019', 'dd.mm.yyyy'));
insert into test values(2, to_date('02.01.2019', 'dd.mm.yyyy'),  to_date('05.01.2019', 'dd.mm.yyyy'));
insert into test values(3, to_date('04.01.2019', 'dd.mm.yyyy'),  to_date('06.01.2019', 'dd.mm.yyyy'));

Мне нужен оператор SELECT, чтобы получить что-то вроде этого:

01.01.2019 1
02.01.2019 2
03.01.2019 2
04.01.2019 2
05.01.2019 2
06.01.2019 1

Ответы [ 3 ]

2 голосов
/ 01 апреля 2019

Другой способ, которым вы можете попробовать использовать cte recursive

WITH   CTE(id,start_date,end_date) AS
(
        SELECT  id,start_date ,end_date
        FROM test
        UNION ALL
        SELECT id,start_date ,cast((end_date - 1) as date)
        FROM CTE 
        WHERE start_date <= cast((end_date - 1) as date)
)
SELECT  end_date,COUNT(*)
FROM    CTE
GROUP BY end_date
ORDER BY end_date

sqlfiddle

Или использовать CONNECT BY

SELECT dt,count(*)
FROM ( 
    SELECT DISTINCT end_date,start_date + LEVEL dt
    FROM    test
    CONNECT BY extract(day from end_date - start_date) - LEVEL + 1 >= 0
) t1
GROUP BY dt
ORDER BY dt

sqlfiddle

1 голос
/ 01 апреля 2019

Ключевым моментом для решения этой проблемы является создание списка дат, для которого вы хотите, чтобы число отдельных идентификаторов было подсчитано.Тогда вы можете просто JOIN этот список с таблицей и включить агрегирование.

Вот простое решение, которое строит список дат из различных значений, доступных в обоих столбцах, содержащих даты в исходной таблице.Существуют и другие (лучшие) варианты с использованием рекурсивного подзапроса или таблицы календаря.

SELECT dt.mydate, COUNT(DISTINCT id_number) cnt
FROM
    ( 
        SELECT DISTINCT start_date mydate FROM test 
        UNION ALL SELECT DISTINCT end_date  FROM test 
    ) dt
    LEFT JOIN test t ON dt.mydate >= t.start_date AND dt.mydate <= t.end_date
GROUP BY dt.mydate
ORDER BY dt.mydate

Эта демонстрация на DB Fiddle с вашими примерами возвращает:

MYDATE                       | CNT
:--------------------------- | --:
01-JAN-19 12.00.00.000000 AM |   1
02-JAN-19 12.00.00.000000 AM |   2
03-JAN-19 12.00.00.000000 AM |   2
04-JAN-19 12.00.00.000000 AM |   2
05-JAN-19 12.00.00.000000 AM |   2
06-JAN-19 12.00.00.000000 AM |   1
0 голосов
/ 01 апреля 2019
SELECT start_date,COUNT(Id_number) from test group by start_date

Этот способ позволяет группировать строки по дате (даты начала или окончания, независимо от того, что вы предпочитаете) и считать строки с одинаковой датой.

Надеюсь, это поможет вам.

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