Lets say I have a table containing several hundred million rows that looks something like this:
memID | foo | bar | foobar 1 | blah | blah | blah 1 | blah | blah | blah 1 | blah | blah | blah 1 | blah | blah | blah 1 | blah | blah | blah 1 | blah | blah | blah 1 | blah | blah | blah 2 | blah | blah | blah 2 | blah | blah | blah 2 | blah | blah | blah 2 | blah | blah | blah 2 | blah | blah | blah . . . 10001 | blah | blah | blah 10001 | blah | blah | blah
I need a query that will return the top N rows for each memID in a range of member IDs. For example, if N = 3 and the range is 0-2 it should return
memID | foo | bar | foobar 1 | blah | blah | blah 1 | blah | blah | blah 1 | blah | blah | blah 2 | blah | blah | blah 2 | blah | blah | blah 2 | blah | blah | blah
I’ve considered a couple approaches, first creating a massive
SELECT TOP (3) * FROM table WHERE memID = 0 UNION ALL SELECT TOP (3) * FROM table WHERE memID = 1 . . .
query in code. This isn’t really a realistic option for probably obvious reasons.
The second approach is to create a temporary table and loop over the range of memIDs inserting the TOP 3 for each memID into that temporary table.
WHILE @MemID < 10000 AND @MemID > 0 BEGIN INSERT INTO tmp_Table SELECT TOP (3) * FROM table WHERE memID = @MemID SET @MemID = @MemID + 1 END
This works, but I’m wondering if there is a more elegant single query solution that I’m missing.
Cadaeic gave me an answer that works without tinkering, but thank you to everyone that suggested analytics, it looks like I have some serious reading to do.
The result:
And here’s the set-up code if you’d like to test locally: