2014-03-31 16 views
5

失败当我运行SQL查询:generate_series()方法红移

select generate_series(0,g) 
from (select date(date1) - date(date2) as g from mytable ; 

它返回一个错误:

INFO: Function "generate_series(integer,integer)" not supported. 
ERROR: Specified types or functions (one per INFO message) not supported 
on Redshift tables. 

但是当我运行此查询:

select generate_series(0, g) from (select 5 as g) 

它返回以下响应:

generate_series 
----------------- 
0 
1 
2 
3 
4 
5 
(6 rows) 

为什么第二个查询可以工作,而第一个查询失败?

+0

显然,第一子查询返回的'interval'不是'integer'(因为:“* generate_series(整数区间)不存在*”) –

+0

在错误消息中看到我的编辑。 – DJo

+3

您没有使用PostgreSQL。您正在使用Amazon Redshift。 –

回答

0

您没有使用PostgreSQL。您正在使用Amazon Redshift。

与Redshift表一起使用时,Amazon Redshift不支持generate_series。它在错误信息中就是这样说的。

要么使用真正的PostgreSQL,要么需要Redshift的功能,还必须在Redshift的限制范围内工作。

你的第二个例子工作,因为它不使用任何Redshift表

+0

这不是一个领导者节点只支持的功能吗? – Naveen

+0

@Naveen也许这是现在,但不是当我写这个。 –

1

这可以在这里使用(pg-9.3.3)也许你的问题只是Redshift-“功能”的结果?

CREATE TABLE mytable 
     (date1 timestamp 
     , date2 timestamp 
     ); 
INSERT INTO mytable(date1,date2) VALUES 
('2014-03-30 12:00:00' , '2014-04-01 12:00:00'); 

SELECT generate_series(0, ss.g) FROM 
    (SELECT date(date2) - date(date1) AS g 
    FROM mytable 
    ) ss ; 
12

generate_series()函数不完全支持Redshift。请参阅开发人员指南的Unsupported PostgreSQL functions部分:

在具体示例中,第二个查询完全在Leader节点上执行,因为它不需要扫描任何实际的表数据,而第一个查询尝试选择数据,这将在计算节点上执行。

5

您可以使用window function获得类似的结果。这需要一个现有的表(如stv_blocklist)播种,至少有你需要的行数,但不会太多,这可能会减慢速度。

with days as (
    select (dateadd(day, -row_number() over (order by true), sysdate::date)) as day 
    from [other_existing_table] limit 30 
) 
select day from days order by 1 asc 

您可以使用此方法获取其他时间范围以及出于分包目的。该版本可生成前一天的所有分钟数据,因此您可以对其进行左连接并存储数据。

with buckets AS (
    select (dateadd(minute, -row_number() over (order by true), sysdate::date)) as minute 
    from [other_table] limit 1440 
) 
select minute from buckets order by 1 asc 

我可能第一次看到这个here

0

上面解释了为什么它不起作用。不过,这个问题“我们能做些什么呢?”开了。

如果您在任何平台(无论是否支持生成器)上开发BI系统,那么使用包含数字和日期序列的维度表非常方便。你如何在Redshift中创建一个?

  1. Postgres里,使用发电机
  2. 出口到CSV
  3. 产生必要的序列创建一个表与在红移同一模式
  4. 导入CSV从步骤2到红移

想象一下,你已经创建了一个非常简单的表,名为calendar

id, date 
1, 2017-01-01 
2, 2017-01-02 
..., ... 
xxx, 2020-01-01 

所以你的查询将是这样的:

SELECT t.id, t.date_1, t.date_2, c.id as date_id, c.date 
FROM mytable t 
JOIN calendar c 
ON c.date BETWEEN t.date_1::date AND t.date_2::date 
ORDER BY 1,4 

在日历表,你也可以拥有的周,月,季,平日第一时间(周一,周二,等等),这使得这样的表超有效用于基于时间的聚合。

1

你是对的,这在Redshift上不起作用。 请参阅here

你可以使用类似这样

with ten_numbers as (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 0) 
,generted_numbers AS 
(
    SELECT (1000*t1.num) + (100*t2.num) + (10*t3.num) + t4.num-5000 as gen_num 
    FROM ten_numbers AS t1 
     JOIN ten_numbers AS t2 ON 1 = 1 
     JOIN ten_numbers AS t3 ON 1 = 1 
     JOIN ten_numbers AS t4 ON 1 = 1 
) 
select gen_num from generted_numbers 
where gen_num between -10 and 0 
order by 1;