2013-06-24 39 views
12

我想在redshift中使用generate series函数,但尚未成功。在redshift中使用sql函数generate_series()

redshift文档说它不受支持。下面的代码不工作:

select * 
from generate_series(1,10,1) 

输出:

1 
2 
3 
... 
10 

我希望做同样的日期。我已经尝试了许多变化,其中包括:

select * 
from generate_series(date('2008-10-01'),date('2008-10-10 00:00:00'),1) 

踢出:

ERROR: function generate_series(date, date, integer) does not exist 
Hint: No function matches the given name and argument types. 
You may need to add explicit type casts. [SQL State=42883] 

也试过:

select * 
from generate_series('2008-10-01 00:00:00'::timestamp, 
'2008-10-10 00:00:00'::timestamp,'1 day') 

并试图:

select * 
from generate_series(cast('2008-10-01 00:00:00' as datetime), 
cast('2008-10-10 00:00:00' as datetime),'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. [SQL State=42883] 

如果不是看起来像我会从另一个后使用此代码:

SELECT to_char(DATE '2008-01-01' 
+ (interval '1 month' * generate_series(0,57)), 'YYYY-MM-DD') AS ym 

PostgreSQL generate_series() with SQL function as arguments

+2

针对您的数据库运行'SELECT version()'来检索您的Postgres版本。 –

+0

有关解决方法,请参阅:http://stackoverflow.com/a/34167753/3019685 – systemjack

+0

我在此处发布了类似问题的解决方法https://stackoverflow.com/questions/22759980/generate-series-method-fails- in-redshift – AlexYes

回答

15

亚马逊Redshift seems to be based on PostgreSQL 8.0.2。 8.4中添加了generate_series()的时间戳参数。

像这样的事情,这避开了这个问题,可能在红移工作。

SELECT current_date + (n || ' days')::interval 
from generate_series (1, 30) n 

它在PostgreSQL 8.3中工作,这是我可以测试的最早版本。它在8.0.26中有记录。

后来。 。 。

看来generate_series() is unsupported在Redshift中。但鉴于你已经验证select * from generate_series(1,10,1)确实工作,上面的语法至少给你一个战斗的机会。 (尽管间隔数据类型也被记录为在Redshift上不受支持。)

更晚。 。 。

您也可以创建一个整数表。

create table integers (
    n integer primary key 
); 

无论你喜欢如何填充它。您可能能够在本地使用generate_series(),转储表并将其加载到Redshift上。 (我不知道;我不使用Redshift。)

无论如何,您可以对该表执行简单的日期算术,而不必直接引用generate_series()或间隔数据类型。

select (current_date + n) 
from integers 
where n < 31; 

至少在8.3中起作用。

+3

+1这似乎解释了它。从亚马逊不到令人印象深刻的... –

7

今天使用Redshift,您可以使用日期时间函数生成一系列日期并输入数字表。

select (getdate()::date - generate_series)::date from generate_series(1,30,1) 

生成这对我来说

date 
2015-11-06 
2015-11-05 
2015-11-04 
2015-11-03 
2015-11-02 
2015-11-01 
2015-10-31 
2015-10-30 
2015-10-29 
2015-10-28 
2015-10-27 
2015-10-26 
2015-10-25 
2015-10-24 
2015-10-23 
2015-10-22 
2015-10-21 
2015-10-20 
2015-10-19 
2015-10-18 
2015-10-17 
2015-10-16 
2015-10-15 
2015-10-14 
2015-10-13 
2015-10-12 
2015-10-11 
2015-10-10 
2015-10-09 
2015-10-08 
+2

虽然这产生了一个系列,我发现没有办法(CTE,子查询,或插入到表或临时表中,将其加入到另一个表进行过滤)。 – cfeduke

+1

@cfeduke你可以将它包装到一个临时表中作为系列AS的'''( select * from generate_series(1,10,1) ) select * from series''' – blotto

+1

@blotto - thank you!你的评论和问题的最后一个例子为我解决了这个问题。 – GeekyDeaks

0

我需要做同样的事情,但超过7天,每隔5分钟。因此,这里是一个基于CTE黑客(丑陋但不是太详细)

INSERT INTO five_min_periods 
WITH 
periods AS (select 0 as num UNION select 1 as num UNION select 2 UNION select 3 UNION select 4 UNION select 5 UNION select 6 UNION select 7 UNION select 8 UNION select 9 UNION select 10 UNION select 11), 
hours AS (select num from periods UNION ALL select num + 12 from periods), 
days  AS (select num from periods where num <= 6), 
rightnow AS (select CAST(TO_CHAR(GETDATE(), 'yyyy-mm-dd hh24') || ':' || trim(TO_CHAR((ROUND((DATEPART (MINUTE, GETDATE())/5), 1) * 5),'09')) AS TIMESTAMP) as start) 
select 
    ROW_NUMBER() OVER(ORDER BY d.num DESC, h.num DESC, p.num DESC) as idx 
    , DATEADD(minutes, -p.num * 5, DATEADD(hours, -h.num, DATEADD(days, -d.num, n.start))) AS period_date 
from days d, hours h, periods p, rightnow n 

应该可以将其扩展到其他生成方案。这里的诀窍是使用笛卡儿积连接(即,无JOIN/WHERE子句)将手工制作的CTE乘以产生必要的增量并应用于锚定日期。