1

処理日の中断がある特定の値のデータを追跡するための最小および最大処理日を見つけようとしています(行は週末には処理されないことに注意してください。同じ値の場合、2つの異なるセットに分割したくありません) )。

SELECT 1, 'A',to_date('10/01/2012','dd/mm/yyyy'), 10, to_date('11/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('11/01/2012','dd/mm/yyyy'), 10, to_date('12/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('12/01/2012','dd/mm/yyyy'), 9, to_date('13/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('13/01/2012','dd/mm/yyyy'), 9, to_date('14/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('16/01/2012','dd/mm/yyyy'), 9, to_date('17/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('17/01/2012','dd/mm/yyyy'), 10, to_date('18/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('18/01/2012','dd/mm/yyyy'), 10, to_date('19/01/2012','dd/mm/yyyy') FROm DUAL;

私の試み(私は間違っていると知っています)

SELECT id, cd, value, min(p_dt) min_dt, max(p_dt) max_dt FROM T
group by id, cd, value;

これは

ID  CD  VALUE   MIN_DT                       MAX_DT
----------------------------------------------------------------------------------
1   A   9   January, 12 2012 00:00:00+0000  January, 16 2012 00:00:00+0000
1   A   10  January, 10 2012 00:00:00+0000  January, 18 2012 00:00:00+0000

返却したいのは

ID  CD  VALUE   MIN_DT                       MAX_DT
----------------------------------------------------------------------------------
1   A   9   January, 12 2012 00:00:00+0000  January, 16 2012 00:00:00+0000
1   A   10  January, 10 2012 00:00:00+0000  January, 11 2012 00:00:00+0000
1   A   10  January, 17 2012 00:00:00+0000  January, 18 2012 00:00:00+0000

これをクエリするさまざまな方法を試しましたが、機能するクエリを作成できませんでした。

SQLフィドル

4

2 に答える 2

0

このサイトには、同じ問題を解決しようとしている他の多くの質問があります。例はhereおよびhereであり、これらは私が回答した質問にすぎません。

週末を無視する必要があるため、この質問はもう少し複雑です。すぐに説明するように、比較的簡単に解決できるようです。

質問には、テーブル内のすべての列の列名が含まれていません。最初の日付は処理日であり、他の日付はこのクエリにとって重要ではないと想定しています。これは間違った仮定かもしれません。

質問からすると、平日(月~木)の場合、翌日に一致する行があればグループが存在するようです。金曜日の場合、次の月曜日に一致する行が必要です。金曜日の場合は 3 日、それ以外の場合は 1 日を追加することでこれを処理します。

クエリの例を以下に示します。SQLFiddle も利用できます

うまくいけば、これで問題が解決します。

with test_data as (
    SELECT 1 as id, 'A' as cd,to_date('10/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('11/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL 
    SELECT 1 as id, 'A' as cd,to_date('11/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('12/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL 
    SELECT 1 as id, 'A' as cd,to_date('12/01/2012','dd/mm/yyyy') as p_date, 9 as value, to_date('13/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL 
    SELECT 1 as id, 'A' as cd,to_date('13/01/2012','dd/mm/yyyy') as p_date, 9 as value, to_date('14/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL 
    SELECT 1 as id, 'A' as cd,to_date('16/01/2012','dd/mm/yyyy') as p_date, 9 as value, to_date('17/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL 
    SELECT 1 as id, 'A' as cd,to_date('17/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('18/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL 
    SELECT 1 as id, 'A' as cd,to_date('18/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('19/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL
)
select 
  id,
  cd,
  value,
  block_num,
  min(p_date) as process_start_date,
  max(p_date) as process_end_date
from (
    select
      id,
      cd,
      value,
      p_date,
      sum(is_block_start) over (partition by id, cd, value order by p_date) as block_num
    from (
        select
          id, 
          cd, 
          value,
          p_date,
          -- get end date of previous block       
          case when lag(case when to_char(p_date, 'DY') = 'FRI' then p_date+3 else p_date+1 end) 
            over (partition by id, cd, value order by p_date) = p_date then 0 else 1 end as is_block_start
        from test_data
        -- Make sure that the data definitely doesn't include Sat or Sun because this could just confuse things
        where to_char(p_date, 'DY') not in ('SAT', 'SUN')
    )
)
group by id, cd, value, block_num
order by id, cd, value, block_num
于 2013-02-20T23:46:11.513 に答える
0

何が欲しいかわからない... 日付で分割するための正しいデータがありません。i_dt が p_dt と等しくなければならないという意味でない限り、日付は一意です。値の代わりに日付で分割しても、単純な選択のようにすべての行が返されます。私の例では、値で分割します。一意の値内の最大日付と最小日付は 1 つだけです。出力を調べます。

SELECT id, cd, i_dt, p_dt, value
 , To_Char(MIN(p_dt) OVER (PARTITION BY value), 'Mon, DD YYYY HH24:MI:SS') min_dt
 , To_Char(MAX(p_dt) OVER (PARTITION BY value), 'Mon, DD YYYY HH24:MI:SS') max_dt
FROM t
/

ID    CD    I_DT           P_DT    VALUE    MIN_DT                 MAX_DT
---------------------------------------------------------------------------------------
1     A    1/14/2012    1/13/2012    9    Jan, 12 2012 00:00:00    Jan, 16 2012 00:00:00
1     A    1/17/2012    1/16/2012    9    Jan, 12 2012 00:00:00    Jan, 16 2012 00:00:00
1     A    1/13/2012    1/12/2012    9    Jan, 12 2012 00:00:00    Jan, 16 2012 00:00:00
1     A    1/19/2012    1/18/2012    10   Jan, 10 2012 00:00:00    Jan, 18 2012 00:00:00
1     A    1/18/2012    1/17/2012    10   Jan, 10 2012 00:00:00    Jan, 18 2012 00:00:00
1     A    1/12/2012    1/11/2012    10   Jan, 10 2012 00:00:00    Jan, 18 2012 00:00:00
1     A    1/11/2012    1/10/2012    10   Jan, 10 2012 00:00:00    Jan, 18 2012 00:00:00
于 2013-02-20T21:30:02.417 に答える