2013-09-26 79 views
5

假設我有填充像這樣的表t如何在SQL中對行的有序子集進行聚合?

x y z 
- - - 
A 1 A 
A 4 A 
A 6 B 
A 7 A 
B 1 A 
B 2 A 

基本上,列x和z是隨機的字母和y的隨機數。

欲聚合的行如下:

x z min(y) max(y) 
- - ------ ------ 
A A 1  4 
A B 6  6 
A A 7  7 
B A 1  2 

換句話說:由於各行用x,y和z排序,選擇每個連續組的最小和最大y的x和z。

注意這個查詢是不是我所需要的:

select x, z, min(y), max(y) 
from t 
group by x, z 

這將導致在以下事與願違的結果:

x z min(y) max(y) 
- - ------ ------ 
A A 1  7 
A B 6  6 
B A 1  2 

所以,問題是:有沒有表達什麼辦法我想在SQL?

(如果該解決方案依賴於SQL方言:一個Oracle解決方案是首選)

+2

我想'B A 1 1'是不需要的行(下面的規格)。 –

+0

很好,很抱歉! – Rubrick

+0

您可以使用[分析函數](http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm) –

回答

2

這裏一個解決方案,但我沒有時間來解釋它一步一步:

select x, z, min(y), max(y) 
from (
    select b.* , sum(switch) over (order by rn) as grp_new 
    from(
    select a.* , 
      case when grp = (lag(grp) over (order by rn)) 
      then 0 
      else 1 end as switch 
    from 
     (select x,y,z, 
       dense_rank() over (order by x, z) as grp, 
       row_number() over (order by x, y, z) rn 
     from t 
    )a 
)b 
)c 
group by x, z, grp_new 
order by grp_new 

SQLFIDDLE to test it.

0

嘗試

select x, z, min(y), max(y) 
    from (select x, z, y from t order by x, z)) 
group by x, z 
+0

來實現它。這會在OP的帖子中輸出相同的不想要的結果。 –

+0

不明白你說的是什麼 – sunysen

1

你沒有提到的Oracle版本,如果你的版本支持WITHROW_NUMBER() OVER

WITH C as 
(
select t.*, 
     ROW_NUMBER() OVER (order by x,y,z) as rn 
from t 
), C2 as 

(
select t1.*, 
( 
    select count(*) from c where Rn<=t1.Rn 
           and (z<>t1.z or x<>t1.x) 
) as Grp 
from c t1 
) 

select x,z,min(y),max(y) from c2 
group by x,z,grp 
order by min(rn) 

SQLFiddle demo

+0

自從Oracle8.2和自9.1以來的公用表表達式以來,窗口函數(又稱「分析」函數)已經可用了。我認爲 –

相關問題