我可以使用框架和滤镜吗?
你 可以的 。但是两者都有限制:
FILTER
子句中的表达式只能看到其获取值的相应行。无法引用窗口函数为其计算值的行。因此 , 除非我们进行 巨大而昂贵的 交叉 联接, 否则我看不到根据 该 行制定过滤器的方法-同一行用于许多不同的计算。或者,我们又回到了LATERAL
那个子查询 可 引用父行。
这些限制使您的特定查询难以实施。现在应该是 正确的 :
SELECt *FROM ( SELECt record_id, security_id, date, price , CASE WHEN do_calc THEN max(earnings) OVER w1 END AS peak_earnings , CASE WHEN do_calc THEN min(earnings) OVER w1 END AS minimum_earnings , CASE WHEN do_calc THEN price / NULLIF(max(earnings) OVER w1, 0) END AS price_to_peak_earnings , CASE WHEN do_calc THEN price / NULLIF(min(earnings) OVER w1, 0) END AS price_to_minimum_earnings FROM ( SELECt *, (date - 365) >= min_date AND s.record_id IS NOT NULL AS do_calc FROM ( SELECt security_id, min_date , generate_series(min_date, max_date, interval '1 day')::date AS date FROM ( SELECt security_id, min(date) AS min_date, max(date) AS max_date FROM security_data GROUP BY 1 ) minmax ) d LEFT JOIN security_data s USING (security_id, date) ) sub1 WINDOW w1 AS (PARTITION BY security_id ORDER BY date ROWS BETWEEN 365 PRECEDING AND 1 PRECEDING) ) sub2WHERe record_id IS NOT NULL ORDER BY 1, 2;
SQL提琴。
笔记问题中没有什么可以说每个
security_id
人在同一天都有行。计算security_id
子查询中每个的最小/最大日期minmax
将为我们提供最短的时间范围。计算的时间范围恰好是该行当前日期之前的365天,并且 不 包括当前行(
ROWS BETWEEN 365 PRECEDING AND 1 PRECEDING
)。通常, 将 当前行从要与当前行进行比较的聚合中 排除 会更有用。
我将计算条件调整到了相同的时间范围,以避免出现极端情况:(date - 365) >= min_date
在小提琴中,在1月1日的每一行中添加了1行,您可以看到leap年与固定天数365天形成对比的效果。leap年(2001,2005,…)之后,窗框为空。
我正在使用所有子查询,通常比CTE快一点。
可以肯定的是,我们需要
ORDER BY
在框架定义中包括。- 我将“ 1年”期间
w1
用作窗口 名称 。您可以添加w2
,等等,每个可以有任意天数。毕竟,如果需要,您可以适应leap年。甚至可能根据当前日期生成整个查询…
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)