【问题标题】:Get max value from a window of rows as new column for all rows从行窗口中获取最大值作为所有行的新列
【发布时间】:2019-08-20 13:51:20
【问题描述】:
| col 1 | col 2 | col 3 |
|-------|-------|-------|
| 67458 | ADM   | 1008  |
| 67458 | ADM   | 1009  |
| 67458 | SKI   | 1009  |
| 67458 | LIS   | 1010  |
| 67458 | TOU   | 1121  |

col2='ADM' 时如何获取col3 的最大值并将其用作其余记录的值?

预期结果:

| col 1 | col 2 | col 3 | col 4 |
|-------|-------|-------|-------|
| 67458 | ADM   | 1008  | 1009  |
| 67458 | ADM   | 1009  | 1009  |
| 67458 | SKI   | 1009  | 1009  |
| 67458 | LIS   | 1010  | 1009  |
| 67458 | TOU   | 1121  | 1009  |

我知道如何使用子选择和所有来做到这一点。 col4 将是一个伪列,用于下游的 JOIN 和其他内容。

我尝试了以下方法,但它填充的是 1121 而不是 1009

MAX(col3) OVER (PARTITION BY col1 (CASE WHEN col2='ADM' THEN col2 END) ORDER BY col1)

【问题讨论】:

    标签: sql amazon-redshift window-functions


    【解决方案1】:

    使用窗口函数:

    select t.*,
           max(col3) filter (where col2 = 'ADM') over (partition by col1) as col4
    from t;
    

    在 Redshift 中,您可能必须使用 case

    select t.*,
           max(case when col2 = 'ADM' then col3 end) over (partition by col1) as col4
    from t;
    

    【讨论】:

    • 感谢您的快速回复。这在 Redshift 中有效吗?
    【解决方案2】:
    SELECT t.*, max(CASE WHEN col2 = 'ADM' THEN col3 END) OVER (PARTITION BY col1) AS col4
    FROM   tbl t;
    

    聚合 FILTER 子句是在 PostgreSQL 9.4 中引入的,对此非常有用。但是 Redshift 不是 Postgres,而且 Postgres 中的大部分后期添加都在那里不受支持。比较:

    【讨论】:

    • 这就是我想要的。感谢您的回复。
    【解决方案3】:

    您可以在 SELECT 中使用子查询来获取该值。

    如果您介意一次又一次地执行它并交叉加入它,这个 suq-query 可以存储在一个变量中。

    架构 (PostgreSQL v10.0)

    CREATE TABLE test (
      "col 1" INTEGER,
      "col 2" VARCHAR(3),
      "col 3" INTEGER
    );
    
    INSERT INTO test
      ("col 1", "col 2", "col 3")
    VALUES
      ('67458', 'ADM', '1008'),
      ('67458', 'ADM', '1009'),
      ('67458', 'SKI', '1009'),
      ('67458', 'LIS', '1010'),
      ('67458', 'TOU', '1121');
    

    查询 #1

    SELECT MAX("col 3") AS "col 4" INTO col4 FROM test t2 WHERE t2."col 2" = 'ADM';
    

    没有要显示的结果。


    查询 #2

    SELECT "col 1",
           "col 2",
           "col 3",
           "col 4"
    FROM test
    CROSS JOIN
    col4;
    

    输出

    | col 1 | col 2 | col 3 | col 4 |
    | ----- | ----- | ----- | ----- |
    | 67458 | ADM   | 1008  | 1009  |
    | 67458 | ADM   | 1009  | 1009  |
    | 67458 | SKI   | 1009  | 1009  |
    | 67458 | LIS   | 1010  | 1009  |
    | 67458 | TOU   | 1121  | 1009  |
    

    View on DB Fiddle

    【讨论】:

    • 感谢您的快速回复。我有这个想法,但测试表真的很大。如果在伪列上使用测试计算会不会是一个糟糕的代码
    • 您可以预先计算值并将其存储在变量中
    【解决方案4】:

    您可以使用相关子查询:

    select t.*,
           (select max(t1.col3) from table t1 where t1.col1 = t.col1 and t1.col2 = 'ADM') as col4
    from table t;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      • 2019-09-22
      • 1970-01-01
      相关资源
      最近更新 更多