Question

I'm trying to LEFT JOIN two tables and GROUP BY a field of the first table in MySQL. If there are multiple rows in the second table for each record in the first one, a GROUP BY eliminates all records but one of the right table. Is there a way to determine which one it is?

To give you a specific example, I want to get a list of users, joined with the IDs of their (for example) most expensive purchases (or most recent purchases, or whatever..) It seems like an easy task, but I'm frustrated and have asolutely no idea how to do it!

Table 1: Users

userId, userName
1       Frank
2       Sarah
3       Tim

Table 2: Purchases

orderId, userId, value
1        3       14.99
2        2       9.99
3        3       79.99
4        1       2.99
5        2       14.99

SELECT * FROM Users LEFT JOIN Purchases ON Users.userId = Purchases.userId

will return:

userId, userName, orderId, value
1       Frank     4        2.99
2       Sarah     2        9.99
2       Sarah     5        14.99
3       Tim       1        14.99
3       Tim       3        79.99

Now if I GROUP BY userId the result will be:

userId, userName, orderId, value
1       Frank     4        2.99
2       Sarah     2        9.99
3       Tim       1        14.99

Is there a way to decide in this case which orderId is kept or is there a completely other and better way to do this? I have tried some things like MAX() but this will always only return the highest value of the whole table, not individually for each user.

Thank you in advance, you awesome stackoverflow-community!

best Florian

Was it helpful?

Solution

In strict SQL this Query would not be valid as in a Group by context u should select only fields contained in the group by clause or aggregates. Mysql however allows this syntax and handles it as "i dont care about this fields", you can not define which of the rows values is selected then.

But you can do it with a query like this: SELECT u.*,p.* FROM Users u LEFT JOIN ( SELECT userId, max(value) as max_value FROM Purchases GROUP BY userId) p ON u.userId = p.userId

OTHER TIPS

If you want to get the max() pusrchase per user preserving the order like orderid etc you may need to do this

select 
u.userId,
u.userName,
p.orderId,
p.value
from Users u
inner join Purchases p on
p.userId = u.userId
  inner join
  (
     select orderId,
     max(value) as value,
     userId
     from Purchases 
     group by userId
  )o
  on o.userId = p.userId
  AND o.value = p.value

group by u.userId

http://sqlfiddle.com/#!2/1afda/9

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top