具有最大和最小日期以及每行关联 ID 的 PostgreSQL 查询

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)

如果多个transes 共享相同的trans_time(即,在同一组数据上运行查询可能会产生不同的结果),这可能不稳定。解决这个问题的一种简单方法,如果有问题,是选择最大或最小 id,例如。当然,这可能会影响结果:)。

如果您使用的是 PostgreSQL 8.4 或更高版本,您也可以使用窗口函数;它们将提供更清晰的查询(如果您熟悉窗口函数就很清楚:),并且它们让您可以执行上述策略很难做到的事情(例如,获取第二个更高的值而不是最大值)。但是,根据我的短暂经验,它们的性能比我在此提出的自联接方法差。Erwin 的答案包含使用窗口函数的查询版本。注意哪个查询执行得更好和/或可以更好地优化(通过添加索引等)会很有趣。