Oracle SQL条件分组

时间:2013-06-07 03:43:59

标签: sql oracle

我有这样的数据集

Name      Service       Continuous      Start          End
A              4                 Y      04/06/2013     31/12/9999 
A              2                 N      02/02/2013     04/02/2013
B              3                 Y      05/06/2013     31/12/9999
B              2                 Y      02/06/2013     04/06/2013
B              5                 Y      27/05/2013     01/06/2013
B              4                 N      13/04/2013     17/04/2013
B              3                 Y      09/04/2013     12/04/2013
B              1                 Y      07/04/2013     08/04/2013

我需要为每个人添加第一组连续服务期。对之前的连续服务期间并不感兴趣,因为标志设置只查看之前的一个时期。所以输出就像:

Name        Current continuous service
A               4
B               10

请B不14。任何人都可以帮我使用plsql吗?

2 个答案:

答案 0 :(得分:2)

无需PL / SQL程序。

窗口(又名“分析”)功能可用于检测连续标志的变化:

select name, sum(service)
from (
    select *,
           case
              when lag(continuous,1,continuous) over (partition by name order by start_date desc) = continuous then 1
              else null
            end as is_valid
    from data_set
) t
where is_valid = 1
group by name;

SQLFiddle示例:http://sqlfiddle.com/#!4/f846b/2

编辑:我注意到这不会仅获得“第一”连续值组。要正确地考虑该限制,需要稍微复杂的查询:

select name, sum(service)
from (
    select *,
           case
              when continuous = 'Y' or lag(continuous) over (partition by name order by start_date desc) is null then 1
              when lag(continuous,1,continuous) over (partition by name order by start_date desc) = continuous then 0
              else null
            end as marker,
            row_number() over (partition by name order by start_date desc) as rn,
            count(case when continuous = 'Y' then 1 else null end) over (partition by name order by start_date desc) as cont_count
    from data_set
) t1
where rn = cont_count 
  and marker = 1
group by name
order by name;

第二个解决方案的SQLFiddle(包括“B”的“第二个”连续组):
http://sqlfiddle.com/#!4/0ca46/2

答案 1 :(得分:0)

假设设置如下:

 SL_NO VAL_1      VAL_2 VAL_3
     1 A              4 Y     
     2 A              2 N     
     3 B              3 Y     
     4 B              2 Y     
     5 B              5 Y     
     6 B              4 N     
     7 B              3 Y     


SET serveroutput ON
DECLARE
     total NUMBER := 0;
BEGIN
     FOR rec IN
     (SELECT DISTINCT val_1 FROM my_test
     )
     LOOP
          FOR rec2 IN
          (SELECT val_1, val_2, val_3
          FROM mY_test
          WHERE val_1 = rec.val_1
          ORDER BY sl_no
          )
          LOOP
               IF rec2.val_3 = 'Y' THEN
                    total   := total + rec2.val_2;
               ELSE
                    dbms_output.put_line(rec2.val_1||' '||' '||total);
               END IF;
          END LOOP;
          total := 0;
     END LOOP;
END;