2017-04-07 57 views
0

我必须优化select查询才能获得更少的no。我们拥有相同的数据但日期不同的记录。我需要按日期对所有行进行排序,并将所有行合并为一个行,直到找到不同的列值。通常数据如下。在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分组。我想我需要额外的订购,并找到新的价值时打破。 在postgres中有没有可用的功能?

回答

3

您可以使用行号差异方法将具有相同c_val的连续行(按日期排序)归入一个组,并在遇到新值时通过新组重新开始。完成此操作后,每个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. 你可以用你的价值lag窗函数来获得以下行(列change)内部的分歧。

  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;