在Redshift中generate_series()方法失败

时间:2014-03-31 11:05:19

标签: amazon-redshift generate-series

当我运行SQL查询时:

 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)

为什么第二个查询有效,而第一个查询失败?

7 个答案:

答案 0 :(得分:13)

Redshift不完全支持generate_series()功能。请参阅开发者指南的Unsupported PostgreSQL functions部分:

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

<强>更新

generate_series现在正在使用Redshift。

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

这将生成过去30天的日期

答案 1 :(得分:6)

您可以使用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

答案 2 :(得分: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;

答案 3 :(得分:0)

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

与Redshift表一起使用时,Amazon Redshift不支持generate_series。它在错误消息中说它就在那里。

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

您的第二个示例有效,因为它不使用任何Redshift表

答案 4 :(得分:0)

这可以在这里工作(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 ;

答案 5 :(得分:0)

上面解释了为什么它不起作用。问题是,我们可以对此做些什么?&#34;开了。

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

    在Postgres中
  1. ,使用生成器生成必要的序列
  2. 导出为CSV
  3. 在Redshift
  4. 中创建一个具有相同架构的表
  5. 将CSV从步骤2导入Redshift
  6. 想象一下,您创建了一个名为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
    

    在日历表中,您还可以拥有周,月,季度,工作日(周一,周二等)的第一个日期,这使得此表对基于时间的聚合非常有效。

答案 6 :(得分:0)

您将需要使用领导者节点支持的功能。诀窍是使用所需的任何表中的row_number()函数。 假设我们要从10天以前的tp开始生成一个日期系列:

   SELECT DATEADD('day', -n, (CURRENT_DATE+1)) AS generated_date
   FROM (SELECT ROW_NUMBER() OVER () AS n FROM my_table LIMIT 10) n
   ORDER BY generated_date DESC

我们得到:

generated_date
2020-06-24 00:00:00
2020-06-23 00:00:00
2020-06-22 00:00:00
2020-06-21 00:00:00
2020-06-20 00:00:00
2020-06-19 00:00:00
2020-06-18 00:00:00
2020-06-17 00:00:00
2020-06-16 00:00:00
2020-06-15 00:00:00