Reputation: 1998
I'm new in SQL querying and I need to get the last position of some players that are active, meaning they have Play value equal to 1. I have to make a join between the table Events
where I have the players activity with columns:
with the table Positions
where I have all players position at every 2-3 seconds with columns:
in order to get the current latitude and longitude of the players that are active.
My current query:
select
e.PlayerId, e.Active,
p.Location.Lat, p.Location.Long,
max_date = max(e.Timestamp),
max_date2 = max(p.Timestamp)
from
Events e
inner join
Positions p on e.PlayerId = p.PlayerId
where
e.Active= 1
group by
e.PlayerId, e.Active, p.Location.Lat, p.Location.Long
but instead of returning 2 rows I get much more. I guess it's because of the b.Location.Lat, b.Location.Long
fields inside the group by clause because the simple query:
select
e.PlayerId, e.Active,
max_date = max(e.Timestamp),
max_date2 = max (p.Timestamp)
from
Events e
inner join
Positions p on e.PlayerId = p.PlayerId
where
e.Active = 1
group by
e.PlayerId, e.Active
returns the correct 2 rows but I need to also get the Lat-Long columns.
UPDATE I found an issue inside my query. When I've run it again for different values I've seen that it returns all the players position if they were even only once active and after that they got inactive. But if the last value for Active (according to the maximum timestamp) for one user is 0, then the query should remove the player location from the response.
Is there any way that I can add those columns without getting more rows than needed?
Upvotes: 1
Views: 484
Reputation: 8113
You could wrap your current query in an outer query, then join to your positions table again. Something like this;
SELECT
base.PlayerId
,base.Active
,base.max_date
,base.max_date2
,p.Location.lat
,p.Location.long
FROM
(
SELECT a.PlayerId ,
a.Active,
max_date = max( a.Timestamp ),
max_date2 = max (b.Timestamp)
FROM Events a
INNER JOIN Positions b
ON a.PlayerId =b.PlayerId
WHERE a.Active= 1
GROUP BY a.PlayerId , a.Active
) base
JOIN Positions p
ON base.PlayerId = p.PlayerId
AND base.max_date2 = p.Timestamp
The reason your other query wasn't working is that you're going to have an entry for each lat & long point. Doing this will give you the unique list that you're after, then joins to Positions again to get lat long info.
Edit: As per the comments, if you want to exclude anybody with the latest Active value set to zero then add this to the end of the code;
JOIN
(
SELECT
e.PlayerID
,MAX(e.Timestamp) Timestamp
FROM Events e
GROUP BY e.PlayerID
) latest
ON base.PlayerID = latest.PlayerID
JOIN Events e2
ON latest.PlayerID = e2.PlayerID
AND latest.Timestamp = e2.Timestamp
WHERE e2.Active <> 0
Upvotes: 1