функция generate_series в Amazon Redshift

Я попробовал следующее:

SELECT * FROM generate_series(2,4);
generate_series
-----------------
           2
           3
           4
(3 rows)

SELECT * FROM generate_series(5,1,-2);                                                             
generate_series
-----------------
           5
           3
           1
(3 rows)

Но когда я пытаюсь,

select * from generate_series('2011-12-31'::timestamp, '2012-12-31'::timestamp, '1 day');

Это сгенерировало ошибку.

ERROR:  function generate_series(timestamp without time zone, timestamp without time zone, "unknown") does not exist
HINT:  No function matches the given name and argument types. You may need to add explicit type casts.

Я использую PostgreSQL 8.0.2 на Redshift 1.0.757.
Есть идеи, почему это происходит?

ОБНОВЛЕНИЕ:

generate_series теперь работает с Redshift.

SELECT CURRENT_DATE::TIMESTAMP  - (i * interval '1 day') as date_datetime 
FROM generate_series(1,31) i 
ORDER BY 1

Это будет генерировать дату последних 30 дней


person DJo    schedule 21.03.2014    source источник
comment
Обходной путь см. на странице stackoverflow.com/a/34167753/3019685.   -  person systemjack    schedule 22.06.2016
comment
Поскольку вы сообщаете, что это работает с Redshift, а redshift не имеет версии, и поэтому старая версия не может использоваться кем-либо, я не понимаю, почему этот вопрос должен оставаться открытым. Я голосую за закрытие.   -  person Evan Carroll    schedule 05.07.2018


Ответы (4)


Версия generate_series(), поддерживающая даты и временные метки, была добавлена ​​в Postgres 8.4.

Поскольку Redshift основан на Postgres 8.0, вам нужно использовать другой способ:

select timestamp '2011-12-31 00:00:00' + (i * interval '1 day')
from  generate_series(1, (date '2012-12-31' - date '2011-12-31')) i;

Если вам «только» нужны даты, это можно сократить до:

select date '2011-12-31' + i
from  generate_series(1, (date '2012-12-31' - date '2011-12-31')) i;
person a_horse_with_no_name    schedule 21.03.2014
comment
ваш первый скрипт дает тот же результат 2011-12-31 00:00:00, 366 раз - person DJo; 21.03.2014
comment
@dhanishjose: интересно. Похоже, что более старые версии Postgres не поддерживают нотацию интервала в стиле ANSI. Смотрите мое редактирование - person a_horse_with_no_name; 21.03.2014
comment
У меня отлично работает на Redshfift. - person slotishtype; 28.11.2014
comment
Вы можете вставить набор результатов из generate_series в таблицу? Я получаю следующую ошибку, когда пытаюсь сохранить его в таблице или использую его в условии соединения — [Amazon] (500310) Недопустимая операция: указанные типы или функции (по одному на сообщение INFO) не поддерживаются в таблицах Redshift. - person Naveen; 07.10.2016
comment
@Naveen это потому, что функция generate_series () доступна только для ведущего узла. Следовательно, вы не можете использовать его при создании временной или постоянной таблицы. - person Bahadir Uyarer; 20.01.2020

generate_series теперь работает с Redshift.

SELECT CURRENT_DATE::TIMESTAMP  - (i * interval '1 day') as date_datetime 
FROM generate_series(1,31) i 
ORDER BY 1

Это будет генерировать дату последних 30 дней

person DJo    schedule 05.06.2018
comment
Кажется, что функция generate_series() поддерживается только на ведущем узле. Выбор из generate_series() работает, но если я попытаюсь вставить результат в таблицу, произойдет сбой. Пользовательские операции с таблицами будут выполняться на вычислительных узлах. - person Dhwani Katagade; 26.09.2019

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

with digit as (
    select 0 as d union all 
    select 1 union all select 2 union all select 3 union all
    select 4 union all select 5 union all select 6 union all
    select 7 union all select 8 union all select 9        
),
seq as (
    select a.d + (10 * b.d) + (100 * c.d) + (1000 * d.d) as num
    from digit a
        cross join
        digit b
        cross join
        digit c
        cross join
        digit d
    order by 1        
)
select (getdate()::date - seq.num)::date as "Date"
from seq;

Функция generate_series(), похоже, еще не полностью поддерживается Redshift. Если я запускаю SQL, упомянутый в ответе DJo, он работает, потому что SQL работает только на ведущем узле. Если я добавлю вставку в dim_time к тому же SQL, это не сработает.

person Dhwani Katagade    schedule 26.09.2019

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

Шаг 1: Создайте таблицу genid и вставьте постоянное значение 1 для количества раз, которое вам нужно для создания серии. Если вам нужно, чтобы серия была сгенерирована за 12 месяцев, вы можете вставить 12 раз. Лучше вы можете вставлять большее количество раз, например, 100, чтобы у вас не возникало никаких проблем.

create table genid(id int)

------------ число месяцев вставить в значения genid(1)

Шаг 2: Таблица, для которой нужно создать ряд.

create table pat(patid varchar(10),stdt timestamp, enddt timestamp);

insert into pat values('Pat01','2018-03-30 00:00:00.0','2018-04-30 00:00:00.0')

insert into pat values('Pat02','2018-02-28 00:00:00.0','2018-04-30 00:00:00.0')

insert into pat values('Pat03','2017-10-28 00:00:00.0','2018-04-30 00:00:00.0')

Шаг 3: Этот запрос создаст серию для вас.

with cte as 
(
select max(enddt) as maxdt
from pat
) ,
cte2 as(
select dateadd('month', -1 * row_number() over(order by 1),  maxdt::date ) as gendt  
from  genid , cte
) select * 
from pat, cte2
where gendt between stdt and enddt
person Partha Sarathi Sarkar    schedule 09.05.2018