Question

I have been trying to get this to work with some row_number, group by, top, sort of things, but I am missing some fundamental concept. I have a table like so:

+-------+-------+-------+
| name  |  ord  |  f_id |
+-------+-------+-------+
| a     |   1   |   2   |
| b     |   5   |   2   |
| c     |   6   |   2   |
| d     |   2   |   1   |
| e     |   4   |   1   |
| a     |   2   |   3   |
| c     |  50   |   4   |
+-------+-------+-------+

And my desired output would be:

+-------+---------+--------+-------+
| f_id  |  ord_n  |  ord   |  name |
+-------+---------+--------+-------+
| 2     |   1     |   1    |  a    |
| 2     |   2     |   5    |  b    |
| 1     |   1     |   2    |  d    |
| 1     |   2     |   4    |  e    |
| 3     |   1     |   2    |  a    |
| 4     |   1     |   50   |  c    |
+-------+---------+--------+-------+

Where data is ordered by the ord value, and only up to two results per f_id. Should I be working on a Stored Procedure for this or can I just do it with SQL? I have experimented with some select TOP subqueries, but nothing has even come close..

Here are some statements to create the test table:

create table help(name varchar(255),ord tinyint,f_id tinyint);
insert into help values
('a',1,2),
('b',5,2),
('c',6,2),
('d',2,1),
('e',4,1),
('a',2,3),
('c',50,4);
Was it helpful?

Solution

You may use Rank or DENSE_RANK functions.

select A.name, A.ord_n, A.ord , A.f_id  from 
  (
    select 
    RANK() OVER (partition by f_id ORDER BY ord asc) AS "Rank", 
    ROW_NUMBER() OVER (partition by f_id ORDER BY ord asc) AS "ord_n", 
    help.*
    from help
  ) A where A.rank <= 2

Sqlfiddle demo

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