admin

PostgreSQL中的自定义聚合函数

sql

通过在当前值(列中的第一个值)中减去初始值(列中的最后一个值),是否可以在PostgreSQL中编写一个聚合函数来计算增量值?它将适用于这样的结构

rankings (userId, rank, timestamp)

并且可以像

SELECT userId, custum_agg(rank) OVER w 
FROM rankings
WINDOWS w AS (PARTITION BY userId ORDER BY timstamp desc)

为userId返回最新条目的等级(按时间戳记)-最旧条目的等级(按时间戳记)

谢谢!


阅读 212

收藏
2021-07-01

共1个答案

admin

最新条目的排名(按时间戳记)-最旧条目的排名(按时间戳记)

现有功能可以通过多种方式来实现。您可以使用现有的窗口函数first_value()last_value(),将其与DISTINCT或结合使用DISTINCT ON,而无需联接和子查询:

SELECT DISTINCT ON (userid)
       userid
     , last_value(rank) OVER w  
     - first_value(rank) OVER w AS rank_delta
FROM   rankings
WINDOW w AS (PARTITION BY userid ORDER BY ts
             ROWS BETWEEN UNBOUNDED PRECEDING
             AND  UNBOUNDED FOLLOWING);

注意窗口功能的自定义框架

或者,您可以在子查询和JOIN中使用基本的聚合函数:

SELECT userid, r2.rank - r1.rank AS rank_delta
FROM  (
  SELECT userid
       , min(ts) AS first_ts
       , max(ts) AS last_ts
   FROM  rankings
   GROUP BY 1
   ) sub
JOIN   rankings r1 USING (userid)
JOIN   rankings r2 USING (userid)
WHERE  r1.ts = first_ts
AND    r2.ts = last_ts;

假设唯一(userid, rank),否则您的要求将是不明确的。

SQL Fiddle演示。

忍者武士

也称为“ 7 Samurai”,
每个请求在注释中, 每个用户ID 仅适用于 最后七个行 (如果有更少,则可以找到尽可能多的 ):

同样,许多可能的方式之一。但我认为这是最短的方法之一:

SELECT DISTINCT ON (userid)
       userid
     , first_value(rank) OVER w  
     - last_value(rank)  OVER w AS rank_delta
FROM   rankings
WINDOW w AS (PARTITION BY userid ORDER BY ts DESC
             ROWS BETWEEN CURRENT ROW AND 7 FOLLOWING)
ORDER  BY userid, ts DESC;

请注意相反的排序顺序。第一行是“最新”条目。我跨过一帧(最多)7行,并仅使用来选择最新条目的结果DISTINCT ON

SQL Fiddle演示。

2021-07-01