Reputation: 5132
I am trying to fetch the last value of player balances in a certain time window.
I have a transactions
table.
The player balance is not the maximum or the minimum one.
SELECT project_id,
player_id,
FIRST_VALUE(balance) OVER (PARTITION BY player_id ORDER BY event_arrival_time DESC) AS balance
FROM transactions
WHERE event_arrival_time BETWEEN '2019-12-02 00:00:00' AND '2019-12-03 23:59:59'
AND project_id='aaa'
GROUP BY project_id, player_id
I get values, but if I test them using the query blown on a single player I get different balance and I see the given result balance somewhere in the middle of the period.
Also, if I run this query several times, I get different balance, like it chooses the different transaction (we are talking about 10 minutes difference).
SELECT *
FROM transacitions
where event_arrival_time BETWEEN '2019-12-02 00:00:00' AND '2019-12-03 23:59:59'
AND project_id='aaa' and player_id = 'player1'
ORDER BY event_arrival_time desc
I want to get list of players in that period, and their latest balance (not MAX value - maybe max date).
Upvotes: 0
Views: 1259
Reputation: 222592
You need filtering, not aggregation.
You can do this with a correlated subquery:
SELECT project_id, player_id, balance
FROM transactions t
WHERE event_arrival_time = (
SELECT MAX(t1. event_arrival_time)
FROM transactions t1
WHERE
t1.player_id = t.player_id
AND t1.event_arrival_time >= '2019-12-02'
AND t1.event_arrival_time < '2019-12-03'
AND t1.project_id = 'aaa'
)
For performance, you want an index on (project_id, player_id, event_arrival_time)
. You might also try a covering index: (project_id, player_id, event_arrival_time, balance)
; with such an index, the database would possibly execute the whole query by looking at the index only, without actually accessing the underlying data.
You can also use window functions:
SELECT project_id, player_id, balance
FROM (
SELECT
t.*,
RANK() OVER(PARTITION BY player_id ORDER BY event_arrival_time DESC) rn
FROM transactions t
WHERE
event_arrival_time >= '2019-12-02'
AND event_arrival_time < '2019-12-03'
AND project_id='aaa'
) t
WHERE rn = 1
Upvotes: 1
Reputation: 15345
I think this should work. Hard to tell without sample.
SELECT
t.project_id,
t.player_id,
GROUP_CONCAT(t.balance) AS Balance -- supposed to have single value
FROM transacitions t
LEFT JOIN transactions t2 ON t.project_id = t2.project_id AND t.player_id = t2.player_id
AND t.event_arrival_time < t2.event_arrival_time
where t2.player_id IS NULL
AND t.event_arrival_time BETWEEN '2019-12-02 00:00:00' AND '2019-12-03 23:59:59'
GROUP BY t.project_id, t.player_id
ORDER BY t.event_arrival_time desc
Upvotes: 0
Reputation: 164154
Remove the GROUP BY
clause and if needed use DISTINCT
in SELECT
:
SELECT DISTINCT
project_id,
player_id,
FIRST_VALUE(balance) OVER (PARTITION BY player_id ORDER BY event_arrival_time DESC) AS balance
FROM transactions
WHERE event_arrival_time BETWEEN '2019-12-02 00:00:00' AND '2019-12-03 23:59:59'
AND project_id='aaa'
Upvotes: 3