I have a martial arts website where I have users in one table and the belts they have earned in another. Here are some example tables / data to help describe my problem:
Users
table :
+---------------------+
| Users |
+---------------------+
| userid | name |
+---------------------+
| 1 | Fred Smith |
+---------------------+
Belts
table :
+------------------------------------------+
| id | userid | belt_colour | awarded_date |
+------------------------------------------+
| 1 | 1 | blue | 2007-01-01 |
+------------------------------------------+
| 2 | 1 | purple | 2008-01-01 |
+------------------------------------------+
| 2 | 1 | brown | 2009-01-01 |
+------------------------------------------+
My problem is this: When you click brown, to view all brown belts I want you to see Fred. I DO NOT want Fred to appear in lists of blue and purple belts (which is what is happening at the moment).
I am struggling to come up with a query that goes something like this:
show me all users where belt=$belt but only if they do not have an entry for a higher belt.
Another example: I am purple but I show up in blue list because details of my blue belt are in the belts table too :-(
Any assistance greatly appreciated!
Assuming a higher belt means a higher awarded_date, one option is to get the MAX
of awarded_date for each user and join back to the belt table:
SELECT u.userId, u.name
FROM Users u
JOIN (
SELECT userId, MAX(awarded_date) max_awarded_date
FROM Belts
GROUP BY userId
) maxb ON u.userId = maxb.userId
JOIN Belts b ON b.userId = maxb.userId
AND b.awarded_date = maxb.max_awarded_date
WHERE b.belt_colour = 'brown'
Sort by _awarded_date_ descending. And limit 1 to the result.
Since every Belt is awarded one after the other, the most recent, is the one that you want to show. So, your query would be like this:
select * from Users u, Belts b where u.userid = b.userid order by awarded_date limit 1;
Hope this helps.
Let's split this problem in two:
So, let's start.
Step 1.a. The most recent belt record for every user
select b.*
from
belts as b
inner join (
select max(id) as maxId from belts group by userId
) as a on b.id = a.maxId
I am assuming that the id
field is always incremental.
Step 1.b. Join step (1.a.) with the user's data
select u.*, b.*
from
users as u
inner join (
select b.*
from
belts as b
inner join (
select max(id) as maxId from belts group by userId
) as a on b.id = a.maxId
) as b on u.userId = b.userId
Step 2. Select all users with a given belt
select u.*, b.*
from
users as u
inner join (
select b.*
from
belts as b
inner join (
select max(id) as maxId from belts group by userId
) as a on b.id = a.maxId
) as b on u.userId = b.userId
where
b.belt_colour = 'brown'
Hope this helps
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.