2013-06-13 30 views
3

我試圖從Oracle查詢創建報告。該數據是這樣的:Oracle 11g:如果行是組中的第一個或最後一個,則只返回一個值

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 

我想要做的是隻返回GROUP_ID當其組中的第一個,也是其他一些價值時,其最後在一組,例如

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 

這可能嗎?

謝謝!

+2

你對「組內第一」和「組內最後」的定義是什麼? – Rene

回答

7

未測試,但這應該是這個想法。如果您需要通過COUNT_1或COUNT_2進行排序,你應該包括它的解析函數over子句中,partition by GROUP_ID order by COUNT_1

參考here理解的解析函數是什麼。

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 
) 
+0

:您的SQL已更正,請查找[鏈接](http://www.sqlfiddle.com/#!4/b0baa/20) –

3
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 
1

您可以嘗試使用lag()lead()分析功能:

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; 

lag(group_id) over (order by group_id, count_1)你得到以前記錄的group_id(其滯後)。同樣,使用lead(group_id) over...您可以獲得下一個記錄的group_id。

隨着case表達,你比較當前group_id下一個以前一個,然後返回適當的值。

+0

感謝您的回答 - 看起來有幾種方法可以實現此目標。我試過了一個修改版的Erkan Haspulat的答案,看起來效果很好,你的答案也是如此。彼此之間是否有任何性能優勢? – user1578653

相關問題