在窗口函数中使用计算列名

时间:2014-12-15 11:55:06

标签: postgresql amazon-redshift

我试图在窗口函数

中使用computed_field
SELECT 
  DATE(activity_date) AS "activity_date",
  activity_app AS "activity_app",
  CASE
    WHEN join_date < 'X' THEN 'A' 
    WHEN join_date < 'Y' THEN 'B' 
    .......
    ELSE 'Unknown' 
  END AS "some_computed_field",
  COUNT(user_id) AS "count_users",
  AVG(count(*)) OVER (PARTITION BY activity_app,some_computed_field ORDER BY activity_date rows BETWEEN 2 preceding and current row) AS "special_average"
  FROM some_table

抛出:

ERROR: column "some_computed_field" does not exist in some_table

我总是可以在窗口函数中编写完整的case语句,但我不想重复。

1 个答案:

答案 0 :(得分:0)

是的,看起来窗函数无法看到伪列所指的内容。我想从计划者的角度来看,当该条目计算如何访问窗口函数内的子集时,该条目是不可解析的。

我想你必须考虑重构查询,以便假冒某列以某种方式真实。

您可以将case语句转换为sql函数compute_field(),然后使用compute_field(join_date),这会导致重复。

CREATE FUNCTION compute_field (join_date TIMESTAMP WITH TIME ZONE) RETURNS TEXT as
$$
SELECT
 CASE
    WHEN join_date < now() THEN 'A' 
    WHEN join_date < now() - interval '1 year'  THEN 'B' 
    ELSE 'Unknown' 
END
$$ language 'SQL';


SELECT 
  DATE(activity_date) AS "activity_date",
  activity_app AS "activity_app",
  compute_field(join_date),
  COUNT(user_id) AS "count_users",
  AVG(count(*)) OVER (PARTITION BY activity_app,compute_field(join_date)  ORDER BY activity_date rows BETWEEN 2 preceding and current row) AS "special_average"
FROM some_table
GROUP BY some_table.activity_date, some_table.activity_app, compute_field(join_date) ;

如果创建函数是一个问题,如果你不介意对表进行双重扫描,你可以将案例包装在CTE中,然后将其加入到结果中,如下所示

WITH computed AS ( SELECT CASE
                              WHEN join_date < now() THEN 'A'
                              WHEN join_date < now() + interval '12 days'  THEN 'B'
                              ELSE 'Unknown'
                          END as "field", 
                  join_date as "jd"
                  FROM some_table )
SELECT
      DATE(activity_date) AS "activity_date",
      activity_app AS "activity_app",
      COUNT(user_id) AS "count_users",
      AVG(count(*)) OVER (PARTITION BY activity_app,computed.field ORDER BY activity_date rows BETWEEN 2 preceding and current row) AS "special_average"
FROM some_table join computed on join_date = jd
GROUP BY some_table.activity_date, some_table.activity_app,computed.field

我已将一些垃圾值替换为SQL,只是为了检查它是否解析(同样为每个非聚合添加了一个GROUP)