Ran*_*Joe 9 postgresql aggregate window-functions
我有下表:
CREATE TABLE trans (
id SERIAL PRIMARY KEY,
trans_date date,
trans_time time
);
Run Code Online (Sandbox Code Playgroud)
我想有以下观点
CREATE OR REPLACE VIEW daily_trans AS
SELECT trans_date,
max(trans_time) as first,
min(trans_time) as last,
calculate_status(min(trans_time), max(trans_time)) as status
GROUP BY trans_date
Run Code Online (Sandbox Code Playgroud)
带有指定最大和最小 trans_time id 的列。
我怎么做?
Erw*_*ter 13
您可以使用窗口函数一步计算:
CREATE OR REPLACE VIEW daily_trans AS
SELECT DISTINCT
trans_date
, first_value(trans_time) OVER w AS first_time
, first_value(id) OVER w AS first_id
, last_value(trans_time) OVER w AS last_time
, last_value(id) OVER w AS last_id
, calculate_status(min(trans_time) OVER w
, max(trans_time) OVER w) AS status
FROM trans
WINDOW w AS (PARTITION BY trans_date ORDER BY trans_time, id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY 1;
Run Code Online (Sandbox Code Playgroud)
我在 window 子句中添加id
了辅助ORDER
列,以在每天相同时间的情况下使排序顺序稳定。
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
是一个不太常用的调整窗口框架的子句,因为我们希望last_value()
总是返回整个分区的最后一个值(日期),而不是根据排序顺序返回当前(包括对等点)的最后一个值。
如何结合DISTINCT
窗口函数:
小智 5
粗略地说,你想要类似的东西
select min_trans_time, min_trans.id as min_trans_time_id,
max_trans_time, max_trans.id as max_trans_time_id
from (
select trans_date,
max(trans_time) as max_trans_time,
min(trans_time) as min_trans_time,
from trans
group by trans_date) min_max_trans,
trans as min_trans,
trans as max_trans
where min_trans.trans_time = min_max_trans.min_trans_time
and max_trans.trans_time = min_max_trans.max_trans_time
Run Code Online (Sandbox Code Playgroud)
如果多个trans
es 共享相同的trans_time
(即,在同一组数据上运行查询可能会产生不同的结果),这可能不稳定。解决这个问题的一种简单方法,如果有问题,是选择最大或最小 id,例如。当然,这可能会影响结果:)。
如果您使用的是 PostgreSQL 8.4 或更高版本,您也可以使用窗口函数;它们将提供更清晰的查询(如果您熟悉窗口函数就很清楚:),并且它们让您可以执行上述策略很难做到的事情(例如,获取第二个更高的值而不是最大值)。但是,根据我的短暂经验,它们的性能比我在此提出的自联接方法差。Erwin 的答案包含使用窗口函数的查询版本。注意哪个查询执行得更好和/或可以更好地优化(通过添加索引等)会很有趣。
归档时间: |
|
查看次数: |
13917 次 |
最近记录: |