Reputation: 2269
I have a table rosters
and a table members
. They are setup like this:
rosters table
id team member
1 1 1
2 1 2
3 1 3
members table
id name last_active
1 Dan 1454815000
2 Ewan 1454817500
3 Cate 1454818369
I need to fetch all rows in rosters
where team=1. Then, I need to take all those returned results and use the member
column to fetch the largest last_active
value from members
where id
is in that list of results returned from rosters
This is how I would do it in PHP, but I'm sure there's a way to just use a more efficient query.
$rosterList = $db->query('SELECT * FROM rosters WHERE team=1');
$lastActive = 0;
foreach($rosterList as $roster) {
$activity = $db->query('SELECT last_active FROM members WHERE id='.$roster['team']);
if ( $activity > $lastActive )
$lastActive = $activity;
}
if ( $lastActive > time()-60 )
echo 'team is currently online';
It would be nice if it could just return one result with the latest last_active
column but if it returns all matches in the members
table that would be fine too.
Upvotes: 0
Views: 71
Reputation: 177
You can use following solution:
$result_array = mysql_query("SELECT * FROM rosters as r INNER JOIN members as m on r.member=m.id AND r.team = '1' ORDER BY last_active DESC LIMIT 1");
$lastActive = 0;
if($result_array)
{
while($row = mysql_fetch_row($result_array,MYSQL_ASSOC))
{
$lastActive = $result_array['last_active'];
}
}
if ( !empty($lastActive) && $lastActive > time()-60 )
echo 'team is currently online';
Upvotes: 1
Reputation: 35593
By using an ORDER BY
(descending) on that last_actie column, then limiting to just 1 row, you get access to the whole member row.
MySQL 5.6 Schema Setup:
CREATE TABLE members
(`id` int, `name` varchar(4), `last_active` int)
;
INSERT INTO members
(`id`, `name`, `last_active`)
VALUES
(1, 'Dan', 1454815000),
(2, 'Ewan', 1454817500),
(3, 'Cate', 1454818369)
;
CREATE TABLE rosters
(`id` int, `team` int, `member` int)
;
INSERT INTO rosters
(`id`, `team`, `member`)
VALUES
(1, 1, 1),
(2, 1, 2),
(3, 1, 3)
;
Query 1:
select
m.*
from members m
join rosters r on m.id = r.member
where r.team = 1
order by m.last_active DESC
limit 1
| id | name | last_active |
|----|------|-------------|
| 3 | Cate | 1454818369 |
Upvotes: 2
Reputation: 108410
I'm a little confused why you are retrieving rows from members
where the id
value matches the team
value from rosters
. Seems like you would want to match on the member
column.
You can use a join operation and an aggregate function. To get the largest value of last_active
for all members of a given team
, using the member
column, something like this:
SELECT MAX(m.last_active) AS last_active
FROM members m
JOIN rosters r
ON r.member = m.id
WHERE r.team = 1
To do the equivalent of the original example, using the team
column (and again, I don't understand why you would do this, because it doesn't look right):
SELECT MAX(m.last_active) AS last_active
FROM members m
JOIN rosters r
ON r.team = m.id
WHERE r.team = 1
The MAX()
aggregate function in the SELECT list, with no GROUP BY
clause, causes all of the rows returned to be "collapsed" into a single row. The largest value of last_active
from the rows that satisfy the predicates will be returned.
You can see how the join operation works by eliminating the MAX()
aggregate...
SELECT m.last_active
, m.id AS member_id
, m.name AS member_name
, r.member
, r.team
, r.id AS roster_id
FROM members m
JOIN rosters r
ON r.member = m.id
WHERE r.team = 1
ORDER BY m.last_active DESC
Upvotes: 1