Создайте новую строку для каждого дня между датами из двух разных столбцов в Redshift SQL - PullRequest
1 голос
/ 19 апреля 2020

Я работаю со столом в Redshift. Он содержит строки с некоторой информацией и двумя датами (дата начала и дата окончания). Я не могу найти способ создать новую строку для каждого дня между начальной и конечной датой. Например, вот код для создания простой таблицы:

CREATE TEMPORARY TABLE dates (name VARCHAR(50), start_date DATETIME, end_date DATETIME)

INSERT INTO dates
VALUES
       ('Peter F.','2018-03-01','2018-03-05'),
       ('Sam R.','2018-04-17', '2018-04-20');

SELECT * FROM dates;

Как мне go из

name          | start_date                | end_date                   | 
Peter F.      | 2018-04-17 00:00:00.000000| 2018-04-20 00:00:00.000000 |
Sam R.        | 2018-03-01 00:00:00.000000| 2018-03-05 00:00:00.000000 |

до:

name          | start_date                | end_date                   | 
Peter F.      | 2018-04-17 00:00:00.000000| 2018-04-20 00:00:00.000000 |
Peter F.      | 2018-04-18 00:00:00.000000| 2018-04-20 00:00:00.000000 |
Peter F.      | 2018-04-19 00:00:00.000000| 2018-04-20 00:00:00.000000 |
Peter F.      | 2018-04-20 00:00:00.000000| 2018-04-20 00:00:00.000000 |
Sam R.        | 2018-03-01 00:00:00.000000| 2018-03-05 00:00:00.000000 |
Sam R.        | 2018-03-02 00:00:00.000000| 2018-03-05 00:00:00.000000 |
Sam R.        | 2018-03-03 00:00:00.000000| 2018-03-05 00:00:00.000000 |
Sam R.        | 2018-03-04 00:00:00.000000| 2018-03-05 00:00:00.000000 |
Sam R.        | 2018-03-05 00:00:00.000000| 2018-03-05 00:00:00.000000 |

Я пытался используя рекурсивный CTE, подобный этому:

WITH cte
     AS (SELECT name,
                start_date,
                end_date
         FROM   dates
         UNION ALL
         SELECT name,
                Dateadd(day, 1, start_date),
                end_date
         FROM   cte
         WHERE  start_date < end_date)
SELECT *
FROM   cte

Но это дает мне ошибку:

[Amazon](500310) Invalid operation: relation "cte" does not exist;

Надеясь на какой-то совет специалиста, поскольку я действительно хотел бы быть в состоянии сделать это в SQL ... Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 19 апреля 2020

Redshift не поддерживает рекурсивные общие табличные выражения.

Один из подходов состоит в создании таблицы чисел:

create table nums(n int);
insert into nums values(0), (1), (2), (3), ...

Затем можно объединить таблицу чисел с исходной таблицей для генерации ожидаемый результат:

select
    d.name,
    dateadd(day, n.n, d.start_date) start_date,
    d.end_date
from dates d
inner join nums n 
    on dateadd(day, n.n, d.start_date) <= d.end_date

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

0 голосов
/ 20 апреля 2020

У вас есть 2 проблемы: во-первых, как создать таблицу диапазонов дат, чтобы объединить ее с датами начала и окончания. Хитрость с Redshift заключается в том, чтобы не полагаться на создание последовательности. Вы можете легко создать последовательность с небольшим перекрестным соединением.

create table ten (X) as select values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
create table (X) thousand as 
select C.X * 100 + B.X * 10 + A.X from ten A
cross join ten B
cross join ten C;

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

GMB дает хороший пример того, как создавать копии всех строк для всех дат между датой начала и конца. Это может быть хорошим способом для go для небольшого числа строк в вашей таблице учетных записей, но я думаю, что вы конкретно говорите о Redshift, есть хороший шанс, что эта таблица довольно большая. Репликация большой таблицы по количеству дней между начальной и конечной датой приведет к очень большому продукту данных, который будет создаваться медленно и займет много разливов на диск. Это проблема № 2 (опять же, если у вас много аккаунтов).

Если это так, то могу я предложить другой подход. Объединение таблицы ваших счетов с таблицей чисел, преобразованной в даты, даст вам точную дату и дату начала и окончания каждой учетной записи. С некоторыми окнами вы можете найти большинство сводок, которые вы, вероятно, ищете, и вам не нужно будет делать массивные изображения данных для этого. Чтобы было ясно, это окупается больше, чем больше стол, но для маленьких столов метод соединения будет лучшим. (2N метод против N раз Даты)

...