2

オブジェクトのIDを考慮して、単一の日付行(必ずしも連続していない)を間隔に追加するクエリが必要です。

次のデータを返すselectクエリがあります

 id       date
9465    12/12/20
9465    12/12/21
9465    12/12/22
9465    12/12/25
9465    12/12/26
9466    12/12/21
9466    12/12/22
9466    12/12/23
9466    12/12/24
9466    12/12/25
9466    12/12/27

上記をサブクエリとして使用すると、次のようなデータが出力されるクエリが必要です。

 id     date_from     date_till
9465    12/12/20      12/12/22
9465    12/12/25      12/12/26
9466    12/12/21      12/12/25
9466    12/12/27      12/12/27
4

3 に答える 3

3

いくつかの分析を使用してこれを行うことができます。

SQL> alter session set nls_date_format='yy/mm/dd';

Session altered.

SQL> select id, min(val) date_from, max(val) date_till
  2    from (select id, val, max(grp) over(partition by id order by val) grp
  3             from (select id, val, lag(val, 1) over(partition by id order by val),
  4                           case
  5                             when lag(val, 1) over(partition by id order by val) < val - 1 then
  6                              row_number() over(partition by id order by val)
  7                             when row_number() over(partition by id order by val) = 1 then
  8                              1
  9                           end grp
 10                      from mytab))
 11   group by id, grp
 12   order by id, date_from
 13  /

        ID DATE_FRO DATE_TIL
---------- -------- --------
      9465 12/12/20 12/12/22
      9465 12/12/25 12/12/26
      9466 12/12/21 12/12/25
      9466 12/12/27 12/12/27

つまり、最初に結果セットをグループに分割します。グループは、特定の ID の連続した日付として定義されます。これを行うには、前の日付をチェックし、その < 現在の行の日付 - 1 かどうかを確認します。lag(val, 1) over(partition by id order by val)

SQL> select id, val, lag(val, 1) over(partition by id order by val),
  2         case
  3           when lag(val, 1) over(partition by id order by val) < val - 1 then
  4            row_number() over(partition by id order by val)
  5           when row_number() over(partition by id order by val) = 1 then
  6            1
  7         end grp
  8    from mytab
  9  /

        ID VAL      LAG(VAL,        GRP
---------- -------- -------- ----------
      9465 12/12/20                   1
      9465 12/12/21 12/12/20
      9465 12/12/22 12/12/21
      9465 12/12/25 12/12/22          4
      9465 12/12/26 12/12/25
      9466 12/12/21                   1
      9466 12/12/22 12/12/21
      9466 12/12/23 12/12/22
      9466 12/12/24 12/12/23
      9466 12/12/25 12/12/24
      9466 12/12/27 12/12/25          6

11 rows selected.

次に空白を埋める必要があります。これにより、空白がその前の null 以外のグループに関連付けられます。つまり、ここでの順序でこれに max() を適用するとmax(grp) over(partition by id order by val)、セット全体の最大ではなく、その時点までに表示された最大行のみが取得されることを意味します。

SQL> select id, val, max(grp) over(partition by id order by val) grp
  2    from (select id, val, lag(val, 1) over(partition by id order by val),
  3                  case
  4                    when lag(val, 1) over(partition by id order by val) < val - 1 then
  5                     row_number() over(partition by id order by val)
  6                    when row_number() over(partition by id order by val) = 1 then
  7                     1
  8                  end grp
  9             from mytab)
 10  /

        ID VAL             GRP
---------- -------- ----------
      9465 12/12/20          1
      9465 12/12/21          1
      9465 12/12/22          1
      9465 12/12/25          4
      9465 12/12/26          4
      9466 12/12/21          1
      9466 12/12/22          1
      9466 12/12/23          1
      9466 12/12/24          1
      9466 12/12/25          1
      9466 12/12/27          6

11 rows selected.

これで、(id, grp) による単純なグループが適用され、id+group ごとに min() と max() が取得されます。

于 2012-12-20T15:36:38.713 に答える
2

私は、分析関数を使用するちょっとしたトリックでこの問題を解決したいと考えています。各行を列挙し、その値を日付から差し引くと、日付は順番に一定です。それが「グループ」IDです。次に、集計の問題は簡単です。

select id, min(date) as date_from, max(date) as date_to
from (select (date - row_number() over (partition by id order by date)) as groupid,
             t.*
      from t
     ) 
group by id, groupid

全体的なステートメントも非常にシンプルです。

私は通常、これに分析関数を使用します。ただし、少なくとも日付演算が機能するデータセットについては、次のことが Oracle で機能する可能性があります。

select id, min(date) as date_from, max(date) as date_to
from (select (date - rownum) as groupid,
             t.*
      from t
      order by id, date
     ) 
group by id, groupid
于 2012-12-20T15:49:07.467 に答える
0

これは「島」問題として知られています。Oracle ベースのソリューションのアプローチを次に示します。

オラクル SQL. どのステートメントを使用すればよいですか

于 2012-12-20T15:37:10.000 に答える