我试图在窗口函数
中使用computed_fieldSELECT
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
语句,但我不想重复。
答案 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)