【问题标题】:Redshift: Generate a sequential range of numbersRedshift:生成一个连续的数字范围
【发布时间】:2021-06-04 01:37:50
【问题描述】:

我目前正在将 PostgreSQL 代码从我们现有的 DWH 迁移到新的 Redshift DWH,并且很少有查询不兼容。 我有一个表,它在一行中包含 id、start_week、end_week 和 orders_each_week。我正在尝试在 start_week 和 end_week 之间生成一个连续系列,以便在给定时间线之间为每周分隔行。

例如, 这是它在表格中的呈现方式

+----+------------+----------+------------------+
| ID | start_week | end_week | orders_each_week |  
+----+------------+----------+------------------+
|  1 |      3     |     5    |        10        | 
+----+------------+----------+------------------+

这就是我想要的方式

+----+------+--------+
| ID | week | orders |
+----+------+--------+
| 1  | 3    | 10     |
+----+------+--------+
| 1  | 4    | 10     |
+----+------+--------+
| 1  | 5    | 10     |
+----+------+--------+

下面的代码抛出错误。

SELECT 
id,
generate_series(start_week::BIGINT, end_week::BIGINT) AS demand_weeks
FROM client_demand
WHERE createddate::DATE >= '2021-01-01'

[0A000][500310] Amazon 无效操作:Redshift 表不支持指定的类型或函数(每条 INFO 消息一个)。 [01000] 不支持函数“generate_series(bigint,bigint)”。

所以基本上我试图找到两个数字之间的连续序列,但我找不到任何解决方案,非常感谢这里的任何帮助。谢谢

【问题讨论】:

标签: sql amazon-redshift generate-series


【解决方案1】:

Gordon Linoff 展示了一种非常常用的方法,这种方法的优点是该过程不会生成不存在的“行”。这可以比动态生成数据的方法更快。但是,您需要有一个大约放置正确行数的表,但情况并非总是如此。他还表明,这个数字系列需要与您的数据交叉连接才能执行您需要的功能。

如果您需要在不使用现有表格的情况下生成大量数字系列,有多种方法可以做到这一点。这是我的方法:

WITH twofivesix AS (
SELECT
    p0.n
    + p1.n * 2
    + p2.n * POWER(2,2)
    + p3.n * POWER(2,3)
    + p4.n * POWER(2,4)
    + p5.n * POWER(2,5)
    + p6.n * POWER(2,6)
    + p7.n * POWER(2,7)
    as n
  FROM
    (SELECT 0 as n UNION SELECT 1) p0,
    (SELECT 0 as n UNION SELECT 1) p1,
    (SELECT 0 as n UNION SELECT 1) p2,
    (SELECT 0 as n UNION SELECT 1) p3,
    (SELECT 0 as n UNION SELECT 1) p4,
    (SELECT 0 as n UNION SELECT 1) p5,
    (SELECT 0 as n UNION SELECT 1) p6,
    (SELECT 0 as n UNION SELECT 1) p7
),
fourbillion AS (
  SELECT (a.n * POWER(256, 3) + b.n * POWER(256, 2) + c.n * 256 + d.n) as n 
  FROM twofivesix a, 
       twofivesix b, 
       twofivesix c,
       twofivesix d
)
SELECT ...

这个例子产生了一大堆数字 (4B),但您可以通过更改表交叉连接的次数和添加 where 子句(如 Gordon Linoff 所做的那样)来扩展或减少系列中的数字。我不希望您需要一个接近这么长的列表,但想展示如何使用它来制作非常长的系列。 (如果这对您更有意义,您也可以使用以 10 为底的写法。)

因此,如果您有一个包含更多行且需要编号的表,那么这可能是最快的方法,但如果您没有这样的表或表长度随时间变化,您可能需要这种纯 SQL 方法。

【讨论】:

    【解决方案2】:

    在 Redshift 不支持的众多 Postgres 功能中,有generate_series()(主节点除外)。您可以自己生成一个。

    如果您在 Redshift 中有一个包含足够多行的表,那么我发现这种方法有效:

    with n as (
          select row_number() over () - 1 as n
          from client_demand cd
         )
    select cd.id, cd.start_week + n.n as week, cd.orders_each_week
    from client_demand cd join
         n
         on n.n <= (end_week - start_week);
    

    这假设您有一个包含足够行的表来为on 子句生成足够的数字。如果表真的很大,那么在n CTE 中添加类似limit 100 的内容来限制大小。

    如果只有少数几个值,您可以使用:

    select 0 as n union all
    select 1 as n union all
    select 2 as n 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 1970-01-01
      • 2013-06-29
      相关资源
      最近更新 更多