Amazon Redshift 中的 generate_series 函数
Posted
技术标签:
【中文标题】Amazon Redshift 中的 generate_series 函数【英文标题】:generate_series function in Amazon Redshift 【发布时间】:2014-04-28 13:30:38 【问题描述】:我尝试了以下方法:
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.
我在 Redshift 1.0.757 上使用 PostgreSQL 8.0.2。 知道为什么会这样吗?
更新:
generate_series 现在正在使用 Redshift。
SELECT CURRENT_DATE::TIMESTAMP - (i * interval '1 day') as date_datetime
FROM generate_series(1,31) i
ORDER BY 1
这将生成最近 30 天的日期
【问题讨论】:
解决方法参见:***.com/a/34167753/3019685 因为您报告这是与 Redshift 一起使用的,而 redshift 没有版本化,因此任何人都无法使用旧版本,我不明白为什么这个问题应该保持开放。我投票结束。 【参考方案1】:在 Postgres 8.4 中添加了支持日期和时间戳的 generate_series()
版本。
由于 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;
【讨论】:
你的第一个脚本给出相同的输出2011-12-31 00:00:00
,366 次
@dhanishjose:很有趣。似乎较旧的 Postgres 版本不支持 ANSI 样式间隔表示法。查看我的编辑
在 Redshfift 上非常适合我。
您能否将结果集从 generate_series 插入到表中?当我尝试将其保存到表中或在连接条件中使用它时出现以下错误 - [Amazon](500310) Invalid operation: Specified types or functions (one per INFO message) not supported on Redshift tables
@Naveen 这是因为 generate_series() 函数仅适用于领导节点。因此,您不能在创建临时表或永久表创建时使用它。【参考方案2】:
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
【讨论】:
【参考方案3】:generate_series 现在正在使用 Redshift。
SELECT CURRENT_DATE::TIMESTAMP - (i * interval '1 day') as date_datetime
FROM generate_series(1,31) i
ORDER BY 1
这将生成最近 30 天的日期
【讨论】:
好像generate_series()函数只在leader节点上支持。来自 generate_series() 的选择有效,但如果我尝试将结果插入表中,它会失败。用户定义的表操作将在计算节点上运行。【参考方案4】:我找到了一个解决方案here,解决了我无法使用 generate_series() 在 Redshift 上生成时间维度表的问题。您可以使用以下 SQL sn-p 生成临时序列。
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;
redshift 似乎还不完全支持 generate_series() 函数。如果我运行 DJo 回答中提到的 SQL,它可以工作,因为 SQL 仅在领导节点上运行。如果我将插入到 dim_time 中添加到相同的 SQL 中,它将不起作用。
【讨论】:
以上是关于Amazon Redshift 中的 generate_series 函数的主要内容,如果未能解决你的问题,请参考以下文章
没有函数或存储过程的 Amazon RedShift 中的 Upsert