我有一个事件数据库,代表用户注册,降级和升级他们的计划。它包含用户密钥,日期密钥和计划密钥。要查找用户当前计划,您需要搜索用户密钥的最新事件,然后使用计划密钥查找与之关联的计划。
然后,为了得到mmr,您只需总结每个用户的计划价格。我有以下SQL来执行此操作;
SELECT SUM(pl_price)
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY t.u_id ORDER BY t.d_iso DESC) rn
FROM (
subscription s INNER JOIN user u ON s.s_userkey = u.u_userkey
INNER JOIN plan pl ON s.s_plankey = pl.pl_plankey
INNER JOIN date d on s.s_datekey = d.d_datekey
) t
) t2
WHERE rn = 1
我现在想要做的是找出每个月的历史mmr。换句话说,它需要为每个月执行上面的sql查询,并忽略它所在月份之后的所有事件。
我该怎么做?我尝试的任何事情都没有接近工作......
编辑:示例表格 - 订阅
s_subkey|s_userkey|s_plankey|s_datekey
1 |2000 |23 |10
...
用户
u_userkey|u_id|u_name|...|
1 |33 |foo |...|
...
计划
pl_plankey|pl_name|pl_price
1 |aplan |10
...
日期
d_datekey|d_date |d_iso |d_yearmonth|...|
1 |10-03-2017|*isodate*|Jun2017 |...|
...
当前查询适用于获取当月的MMR,因此在6月份。我想要一张这样的桌子:
monthyear|mmr
Jan17 |1000000
Feb17 |1100000
Mar17 |1200000
... |...
答案 0 :(得分:0)
这是一种蛮力方法。它生成感兴趣的月份,然后使用此信息计算每个月的值:
SELECT mon, SUM(pl_price)
FROM (SELECT DISTINCT ON s.uid, g.mon) s.uid, g.mon, pl_price
FROM generate_series('2017-01-01'::timestamp, '2017-06-01'::timestamp, interval '1 month') g(mon) CROSS JOIN
subscription s INNER JOIN
user u
ON s.s_userkey = u.u_userkey INNER JOIN
plan pl
ON s.s_plankey = pl.pl_plankey INNER JOIN
date d
ON s.s_datekey = d.d_datekey
WHERE d.date_key <= g.mon
ORDER BY s.uid, g.mon, t.d_iso DESC
) s
GROUP BY mon
ORDER BY mon;
请注意,这使用DISTINCT ON
而不是ROW_NUMBER()
。性能通常会快一点。