1

I have two tables:

table_1
uid | xid | name

table_2
uid | elements | time | pkey

I want to select multiple rows of xid, elements and time where time is the 10 smallest values and uid (or xid) is distinct.

uid, xid in in table_1 is unique and the relationship between uid in table_1 and table_2 is one to many..

I tried something like this but its not really working too well:

SELECT table_1.xid, MIN(table_2.time), table_2.elements
FROM table_1, table_2
WHERE table_1.uid= table_2.uid
GROUP BY table_2.uid
LIMIT 10

Lets take some data to play around with:

table_1
uid | xid | name
1 | 435 | John
2 | 596 | Jane


table_2
uid | elements | time | pkey
1 | 1 | 567 | 0
2 | 2 | 335 | 1
1 | 1 | 435 | 2
1 | 2 | 456 | 3
2 | 1 | 337 | 4
1 | 1 | 428 | 5

How would I select the top 2 distinct results for each UID? In this case:

fid| elements | time
596| 2 | 335
435| 1 | 428

Thanks!!!

In case people don't understand why lexu's solution does not work - it does not bind to primary key on table 2

If I change above data to :

table_2
uid | elements | time | pkey
1 | 1 | 567 | 0
2 | 2 | 335 | 1
1 | 1 | 435 | 2
1 | 2 | 456 | 3
2 | 1 | 337 | 4
1 | 2 | 428 | 5

Keep table_1 the same then the result should be:

fid| elements | time
596| 2 | 335
435| 2 | 428

but with @lexu's solution result is:

fid| elements | time
596| 2 | 335
435| 1 | 428

Nonetheless, thanks everyone for the help and especially @eagle!

5
  • Don't you forget something? what is the connection between these tables? xid -> uid? Doesn't JOIN + GROUP BY work for you? Commented May 6, 2010 at 7:42
  • uid -> uid.. I'll explain more above.. Commented May 6, 2010 at 7:53
  • do your group by on XID .. then it should work Commented May 6, 2010 at 8:07
  • 1
    10 smallest over the whole of table_2 or 10 smallest for each uid or 10 uids that have smallest time in table_2? :) you have to be precise with SQL, then it becomes much easier :) Commented May 6, 2010 at 8:08
  • 10 smallest time in table_2 for distinct uid.. Commented May 6, 2010 at 8:21

1 Answer 1

1

Here's my solution. I thought that rather than just give the working query, I will go step-by-step through my thought process and the queries I tried in each step:

First, let's select the 10 smallest times for distinct uid:

select uid, min(time)
from table_2
group by uid
order by 2
limit 10

This gives us:

uid | time
2 | 335
1 | 428

That was easy... unfortunately, this doesn't allow us to grab the primary key, which will be a problem if the following row is added:

table_2
uid | elements | time | pkey
1 | 2 | 428 | 6

In future queries, when we try to join on the time and uid, we will get two records rather than 1. So we need a better query that returns a distinct value (e.g. pkey) rather than the time, which I am assuming can be non-distinct...

Note: This would be much simpler if MySQL had the FIRST() or LAST() aggregate functions. Unfortunately, it doesn't so we must settle for a sub-query, order-by, limit combo.

select
  t2.uid,
  (select pkey from table_2 t3 where t2.uid = t3.uid order by t3.time asc limit 1) as minpkey
from
  (select uid, min(time) from table_2 group by uid order by 2 limit 10) t2

This will now return results we can work with:

uid | minpkey
1 | 5
2 | 1

Notice that the 5 was chosen randomly and the 6 could have just as easily been chosen; it all depends on how mysql decides to choose it. But for us, it doesn't matter.

Next we want to show more data (namely the xid and elements fields):

select t1.xid as fid, t5.elements, t5.time
from 
(select
  t2.uid,
  (select pkey from table_2 t3 where t2.uid = t3.uid order by t3.time asc limit 1) as minpkey
from
  (select uid, min(time) from table_2 group by uid order by 2 limit 10) t2
) t4
inner join table_1 t1 on (t4.uid = t1.uid)
inner join table_2 t5 on (t4.minpkey = t5.pkey)

And viola, it should return the exact same data you provided in your example! It might not be very efficient, but it should work!

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks - thats great - now I guess I need to see if I can either make my tables more efficient or my query more efficient!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.