I have a table that acts like a ledger where each row has a column that contains either a positive or negative number, as well as a secondary number that I'll need to get a sum on.
id | coins | value | user_id | created |
---|---|---|---|---|
UUID1 | 25 | 0 | UUID42 | datetime |
UUID2 | -25 | 0 | UUID42 | datetime |
UUID3 | 50 | 599 | UUID42 | datetime |
UUID4 | 25 | 0 | UUID13 | datetime |
UUID5 | 25 | 399 | UUID42 | datetime |
UUID6 | 100 | 1099 | UUID42 | datetime |
UUID7 | 25 | 299 | UUID42 | datetime |
Using this table, say that user UUID42
is spending 100 coins. I need to get back records UUID3, UUID5, and UUID6 because the SUM(coins) >= 100
, but not record UUID7 since the other 3 already fulfill the criteria. Once I have all of those records back, I'll be able to sum the value and do other processing, but I'll need to individual records returned because I need to know their individual values since it's not a simple SUM(value)
.
Here's where I'm at currently (as provided by Stu, but slightly modified).
with rt as (
select *,
sum(coins) over(partition by user_id order by created) running
from t
), valid as (
select *,
case when lag(running) over(partition by user_id order by created)<running then 1 else 0 end cons
from rt
where user_id = 'UUID42' and running - 100 < 100
)
select id, coins, value
from valid
where cons = 1
The issue I'm having from this query is that if the user spends 49 coins, then only record UUID3 needs to be returned because the 50 coins in that record cover the 49 needed, but I'm getting both 3 & 5 returned. Then, if the user is only spending 1 coin, again only record UUID3 should be returned, but nothing is returned.
I'm using postgres, but if anyone knows how it can be done in another engine, I'm sure I can get it close.
EDIT: The answer @Stu gave is super close, and gives me the answer to my original question, but it turns out that it only really works for that one case. I've updated my question to better clarify what I'm looking for.