2017-04-07 20 views
0

少ないクエリを得るためにselectクエリを最適化する必要があります。我々は同じデータを持っているが、異なる日付を持つときのレコードの。すべての行を日付別にソートする必要があり、異なる列の値が見つかるまで、すべての行を1つにまとめてください。通常、データは次のようになります。複数のセットを持つレコードをSQLでグループ化する

date  c_val 
1/1/2016 200 
2/1/2016 200 
3/1/2016 300 
4/1/2016 300 
5/1/2016 300 
6/1/2016 200 
7/1/2016 200 

次に、出力は次のようになります。

start_date end_date c_val 
1/1/2016 2/1/2016 200 
3/1/2016 5/1/2016 300 
6/1/2016 7/1/2016 200 

私は今のところ、その後のクエリは、このようなものです:

select min(date) as start_date, max(date) as end_date, c_val 
from t_ord 
group by c_val; 

しかし、それはc_valでグループ化され、これは実際には2つだけのレコードを返しています。私は、新しい価値を見いだすためには、秩序と崩壊に新たな必要があると思う。 ポストグルで利用できる機能はありますか?

答えて

3

行番号の違いを利用して、同じc_valを持つ連続した行(日付順)を1つのグループに分類し、新しい値に遭遇したときに新しいグループを開始することができます。これが完了したら、c_valごとに各グループの日付minmaxを取得します。

select min(date) as startdate,max(date) as enddate,c_val 
from (select c_val,date,row_number() over(order by date) 
         -row_number() over(partition by c_val order by date) as grp 
     from t_ord 
    ) t 
group by c_val,grp; 
+0

かなりクールなソリューションです! –

1
  1. 次の行(列change)内の差異を得るために、あなたの価値にlag窓関数を使用することができます。

  2. 次に、数値をグループ化するウィンドウ関数としてsumに入力します(列gr)。

  3. 変更されていない値のシーケンスのグループを持つことで、値と値そのものをグループ化し、各グループの最小日と最大日を取得できます。以下は

クエリです:

select 
    min(date) as start_date, max(date) as end_date, c_val 
from (
    select 
    c_val, sum(change) over (order by date) as gr, date 
    from (
    select 
     c_val, 
     case when lag(c_val) over (order by date) <> c_val then 1 else 0 end as change, 
     date 
    from t_ord 
    ) seq_change 
) groups_of_values 
group by c_val,gr 
order by start_date; 
関連する問題