Here is what my data looks like:
item_ID | group_ID | count_of_items_in_group
2|ABC|3
5|ABC|3
9|ABC|3
29|DEF|3
3|DEF|3
4|DEF|3
200|XYZ|2
300|XYZ|2
6
Use the ROW_NUMBER()
function for this:
SELECT *
FROM (select *,ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY item_id) as RowRank
from items_in_groups
)sub
WHERE RowRank <=2
Demo: SQL Fiddle
The ROW_NUMBER()
function assigns a number to each row. PARTITION BY
is optional, but used to start the numbering over for each value in that group, ie: if you PARTITION BY group_id
then for each unique group_id
value the numbering would start over at 1. ORDER BY
of course is used to define how the counting should go, and is required in the ROW_NUMBER()
function.
Can do this as a min and a max select statement, union them together and group by to eliminate any duplicates that one row groups would provide
select item_id, group_id
from(
(select max(item_id) as item_id, group_id from table group by group_id) a
union all
(select min(item_id) as item_id, group_id from table group by group_id) b) qry
group by item_id,group_id
Not the prettiest I'm sure, but it works. It's usually best to have some type of logic built in, not "I do not care which 2 are returned."
(Edit - I put the groupID in the groupo by and not item_ID. Ha, silly mistake I'll blame on dyslexia. Corrected now)
What about using ROW_NUMBER() to enum the number of fields of your data set, partitioned by each group_id.
And after that just return when is just less or equal to 2? or any number that you want
SELECT * FROM
(
select item_id, group_id, count_of_items,
ROW_NUMBER() OVER(PARTITION BY group_id ORDER BY count_of_items DESC)
AS RN
from items_in_groups
) A
WHERE RN <= 2
Here is the Sql Fiddle