是否有可能在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返回最新条目的排名(按时间戳) - 最旧条目的排名(按时间戳记)
谢谢!
答案 0 :(得分:1)
你可以在Postgres中使用JOIN和DISTINCT ON来完成。 GRP
查询会为您提供每个rank
的最新userID
值,因此只需将rankings
加入user_id
并减去值。
SELECT rankings.userId,
rankings.rank-GRP.rank as delta,
rankings.timestamp
FROM rankings
JOIN
(
SELECT DISTINCT ON (userId) userId, rank, timestamp
FROM rankings
ORDER BY userId, timestamp DESC
) as GRP ON rankings.userId=GRP.userId
答案 1 :(得分:1)
最新条目的排名(按时间戳) - 最旧条目的排名(按时间戳记)
有许多方法可以通过现有功能实现这一目标。
您可以使用现有的window functions first_value()
and 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);
请注意自定义frames for the window functions!
或者您可以在子查询和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)
,或者您的要求不明确。
... a.k.a. "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
的最新条目的结果。