Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to create a report from an Oracle query. The data is like this:

GROUP_ID | COUNT_1 | COUNT_2
    1    |   100   |   123
    1    |   101   |   123
    1    |   283   |   342
    1    |   134   |   123
    2    |   241   |   432
    2    |   321   |   920
    2    |   432   |   121
    2    |   135   |   342

What I would like to do is only return the GROUP_ID when its the first in the group, and also some other value when its the last in the group, e.g.

GROUP_ID | COUNT_1 | COUNT_2
    1    |   100   |   123
         |   101   |   123
         |   283   |   342
   last  |   134   |   123
    2    |   241   |   432
         |   321   |   920
         |   432   |   121
   last  |   135   |   342

Is this possible?

Thanks!

share|improve this question
2  
What is your definition of "first in the group" and "last in the group"? – Rene 8 hours ago

3 Answers

You can try using the lag() and lead() analytical functions:

with a as (
   select 1 group_id, 100 count_1, 123 count_2 from dual union all
   select 1 group_id, 101 count_1, 123 count_2 from dual union all
   select 1 group_id, 283 count_1, 342 count_2 from dual union all
   select 1 group_id, 134 count_1, 123 count_2 from dual union all
   select 2 group_id, 241 count_1, 432 count_2 from dual union all
   select 2 group_id, 321 count_1, 920 count_2 from dual union all
   select 2 group_id, 432 count_1, 121 count_2 from dual union all
   select 2 group_id, 135 count_1, 342 count_2 from dual 
)
select
  case lag (group_id) over (order by group_id, count_1) 
    when group_id then 
      case lead (group_id) over (order by group_id, count_1)
      when group_id then null
           else 'last'
      end
    else to_char(group_id) end x,
  count_1,
  count_2
from
a;

with lag(group_id) over (order by group_id, count_1) you get the group_id of the previous record (it lags behind). Similarly, with lead(group_id) over... you get the group_id of the next record.

With the case expression, you compare the current group_id with the next and previous one and then return the appropriate value.

share|improve this answer
Thanks for your answer - it looks like there are several ways of achieving this. I've tried out a modified version of Erkan Haspulat's answer which seemed to work fine, as does your answer. Are there any performance benefits of one over the other? – user1578653 7 hours ago

Not tested, but this should be the idea. If you need to sort by COUNT_1 or COUNT_2, you should include it in the analytic functions' over clause, partition by GROUP_ID order by COUNT_1

Refer here to understand what an analytic function is.

select
  case when ROW_NUMBER = 1 then GROUP_ID
       when ROW_NUMBER = GROUP_COUNT then 'last'
       else NULL
  end GROUP_ID
  ,COUNT_1
  ,COUNT_2
from(
    select
      GROUP_ID
      ,COUNT_1
      ,COUNT_2
      ,row_number() over(partition by GROUP_ID) ROWNUMBER
      ,count(GROUP_ID) over (partition by GROUP_ID) GROUP_COUNT
    from
      FOO
)
share|improve this answer
:Your SQL is corrected ,please find the link – Gaurav Soni 8 hours ago
CREATE TABLE tt(g NUMBER, c1 NUMBER, c2 NUMBER);
INSERT INTO tt VALUES(1, 100, 123);
INSERT INTO tt VALUES(1, 101, 123);
INSERT INTO tt VALUES(1, 283, 342);
INSERT INTO tt VALUES(1, 134, 123);
INSERT INTO tt VALUES(2, 241, 432);
INSERT INTO tt VALUES(2, 321, 920);
INSERT INTO tt VALUES(2, 432, 121);
INSERT INTO tt VALUES(2, 135, 342);

SELECT CASE WHEN 1=ROW_NUMBER() OVER (PARTITION BY g ORDER BY c1 ASC,  c2 ASC) THEN '1'
            WHEN 1=ROW_NUMBER() OVER (PARTITION BY g ORDER BY c1 DESC, c2 DESC) THEN 'Last'
            ELSE 'Empty'
        END answer,
       c1, c2
  FROM tt;

1        100  123
Empty    101  123
Empty    134  123
Last     283  342
1        135  342
Empty    241  432
Empty    321  920
Last     432  121
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.