2

我需要一个查询,它将单个日期行(不一定是连续的)添加到间隔中,同时考虑到对象的 id。

我有一个选择查询,它返回以下数据

 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

即首先我们将结果集分成组,其中组被定义为给定I​​D 的连续日期。我们通过检查之前的日期并查看它是否 < 当前行 date - 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.

我们接下来需要填写空白,以便空白与之前的非空组相关联。即,我们将 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.

现在它是一个简单的 group by (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 回答