按时间范围对数据进行分组

时间:2014-06-03 04:44:58

标签: sql oracle oracle11g oracle10g

我要求在val = 'Y'col_val < 5的条件下获得开始时间和结束时间。

我有一个名为temp_vvv结构的表,如

date_time             |     val    |  col_val
-------------------------------------------------------------------------
03/06/2014 08:58:00         Y          4
03/06/2014 08:59:00         Y          3
03/06/2014 09:00:00         Y          1
03/06/2014 09:01:00         Y          0
03/06/2014 09:01:30         Y          0
03/06/2014 09:02:00         Y          2
03/06/2014 09:02:30         Y          5
03/06/2014 09:03:00         Y         20
03/06/2014 09:03:30         Y         50
03/06/2014 09:04:00         Y         55
03/06/2014 09:04:30         Y         60
03/06/2014 09:05:00         Y         10
03/06/2014 09:05:30         Y          4
03/06/2014 09:06:00         Y          2
03/06/2014 09:06:30         Y          0
03/06/2014 09:07:00         Y          0
03/06/2014 09:07:30         Y          1
03/06/2014 09:08:00         N          5
03/06/2014 09:08:30         N          0 

我期待像

这样的输出
  start_date_time       |     end_date_time
 --------------------------------------------------
 03/06/2014 08:58:00         03/06/2014 09:02:00
 03/06/2014 09:05:30         03/06/2014 09:07:30

如何从选择查询中获取此输出

请帮帮我。

修改

col_val&lt; 5的值从'03/06/2014 08:58:00'开始,到'03/06/2014 09:02:00'结束。所以第一条记录为start_date_time'03/06/2014 08:58:00'end_date_time'03/06/2014 09:02:00'等等。

如何实现它?

3 个答案:

答案 0 :(得分:2)

您可以使用ROW_NUMBER()分析功能根据COLCOL_VAL对记录进行分组。

尝试使用以下查询,

SELECT MIN(date_time) start_date_time, MAX(date_Time) end_date_time
FROM(
    SELECT date_time, val, col_val, CASE WHEN val = 'Y' AND col_val < 5 THEN 1 ELSE 0 END col_val_limit,
                  ROW_NUMBER() OVER (ORDER BY DATE_TIME) - 
          ROW_NUMBER() OVER (PARTITION BY CASE WHEN val = 'Y' AND col_val < 5 THEN 1 ELSE 0 END ORDER BY DATE_tIME) grp
    FROM    temp_vw
    )
WHERE  col_val_limit = 1
GROUP BY grp
ORDER BY start_date_time;

答案 1 :(得分:1)

select
  min(date_time),
  max(date_time)
from (
  select
    date_time,
    sum(new_group) over (order by date_time) group_
  from (
    select
      date_time,
      val,
      col_val,
      case when
        case when lag(val    ) over (order by date_time) = 'Y' and
                  lag(col_val) over (order by date_time) <  5  then
             1
        else 0 end 
        !=
        case when val = 'Y' and
                  col_val < 5 then
             1
        else 0 end
      then
        1
      else
        0
      end              new_group
    from
      tq84_t
  )
  where
    val = 'Y' and col_val < 5
)
group by group_;

这里是SQL Fiddle

答案 2 :(得分:0)

未经测试,但其目的是根据群组的开始时间识别每一行所属的群组。通过获取最低日期有效行(val ='Y'和col_val ='5')来确定开始时间,其中中间不存在无效行。最后,按开始时间对行进行分组,并使用MAX

检索结束时间
SELECT min_time start_date_time, MAX(date_time) end_date_time
FROM (
    SELECT
    date_time,
    (
        SELECT MIN(date_time)
        FROM temp_vvv t2
        WHERE val = 'Y' AND col_val < 5
        AND NOT EXISTS (SELECT 1 FROM temp_vvv t3
            WHERE t3.date_time BETWEEN t2.date_time AND t1.date_time
            AND (t3.val <> 'Y' OR t3.col_val >= 5)
        )
    ) min_time
    FROM temp_vvv t1
    WHERE t1.val = 'Y'
    AND t1.col_val < 5
) GROUP BY min_time

http://sqlfiddle.com/#!4/64545/8