需要Oracle sql查询来分组日期

Moh*_*lim 3 sql oracle oracle11g gaps-and-islands

我的桌子的日期是2015年11月2日至2015年12月1日.例如...

ATTNDATE
--------
02/11/2015
03/11/2015
--
--
--
01/12/2015.
Run Code Online (Sandbox Code Playgroud)

此表可能还有一些缺失日期.让我们假设此表中缺少06/11/2015和20/11/2015.

我希望得到像这样的输出

SL.No      ATTNFROM          ATTNTILL
  1.       02/11/2015        05/11/2015
  2.       07/11/2015        19/11/2015
  3.       21/11/2015        01/12/2015
Run Code Online (Sandbox Code Playgroud)

请帮助我在oracle plsql中获取此输出

Ale*_*ole 6

您可以使用超前和滞后分析函数来执行此操作 - 在子组中,然后将其分组,这可能是您错过的 - 但您也可以使用分析"技巧"来执行此操作.

如果你查看每个日期和最低日期之间的差异,你得到一个破碎的序列,在你的情况下,0,1,2,3,5,...,27,28,29.你可以看到attndate - min(attndate) over ().

你还有另一个完整的序列row_number() over (order by attndate),它给你1,2,3,... 28.

如果从另一个中减去一个,则每个连续的日期块都会得到相同的答案,我称之为'slot_no':

select attndate,
  attndate - min(attndate) over ()
    - row_number() over (order by attndate) as slot_no
from your_table;
Run Code Online (Sandbox Code Playgroud)

使用这些数据,每一行都会得到-1,0或1.(如果需要,可以添加两行以使它们更友好,但只有在数据中的间隙为单日时才能正常工作).然后,您可以按该插槽号分组:

with cte as (
  select attndate,
    attndate - min(attndate) over ()
      - row_number() over (order by attndate) as slot_no
  from your_table
)
select dense_rank() over (order by slot_no) as slot_no,
  min(attndate) as attnfrom, max(attndate) as attntill
from cte
group by slot_no
order by slot_no;
Run Code Online (Sandbox Code Playgroud)

使用一些生成的数据:

alter session set nls_date_format = 'DD/MM/YYYY';
with your_table (attndate) as (
  select date '2015-11-02' + level - 1 from dual connect by level <= 4
  union all select date '2015-11-07' + level - 1 from dual connect by level <= 13
  union all select date '2015-11-21' + level - 1 from dual connect by level <= 11
),
cte as (
  select attndate,
    attndate - min(attndate) over ()
      - row_number() over (order by attndate) as slot_no
  from your_table
)
select dense_rank() over (order by slot_no) as slot_no,
  min(attndate) as attnfrom, max(attndate) as attntill
from cte
group by slot_no
order by slot_no;

   SLOT_NO ATTNFROM   ATTNTILL 
---------- ---------- ----------
         1 02/11/2015 05/11/2015
         2 07/11/2015 19/11/2015
         3 21/11/2015 01/12/2015
Run Code Online (Sandbox Code Playgroud)

如果您的真实场景是获取多个键的这些范围,例如人员ID,那么您可以partition by在三个over ()部分中为每个分析函数调用添加一个子句.