Oracle查询以查找活动状态记录的开始和结束日期

时间:2019-04-06 12:12:34

标签: sql oracle

我有以下数据

+------+-----------+----------+-------+------------+
| Code | StartDate | EndDate  | Unit  | CodeStatus |
+------+-----------+----------+-------+------------+
| 1001 |  20100101 | 20101231 | UnitA | Active     |
| 1001 |  20110101 | 20151231 | UnitB | Active     |
| 1001 |  20160101 | 21000101 | UnitB | Inactive   |
| 1002 |  20160101 | 20181231 | UnitA | Active     |
| 1002 |  20190101 | 21000101 | UnitA | Inactive   |
| 1003 |  20140101 | 21000101 | UnitC | Active     |
+------+-----------+----------+-------+------------+

如果我们看第一个代码(1001),则有两个活动记录,在输出中,我想要活动记录的最小开始日期和最高结束日期。如下

+------+-----------+----------+----------+
| Code | StartDate | EndDate  | Status   |
+------+-----------+----------+----------+
| 1001 | 20100101  | 20151231 | Inactive |
| 1002 | 20181231  | 20181231 | Inactive |
| 1003 | 20140101  | 21000101 | Active   |
+------+-----------+----------+----------+

此表有大约一百万条记录,我使用api提取数据,因此性能也很重要。

有人可以帮助我进行查询。

4 个答案:

答案 0 :(得分:1)

您似乎想要激活代码的时间段以及当前状态。这是一个基本的聚合查询,具有以下特点:

select code,
       min(case when codestatus = 'Active' then start_date end) as active_start_date,
       max(case when codestatus = 'Active' then end_date end) as active_end_date,
       max(codestatus) keep (dense_rank first order by start_date desc) as current_code_status
from codes
group by code;

keep是Oracle中的一个不错的功能,它本质上是一个聚合的first_value()函数。

答案 1 :(得分:0)

您只需要max和min聚合函数

   with cte as
  (
   select code,min(StartDate) as mStartDate,
   max(EndDate)  as mEndDate from table
   where CodeStatus='Active' group by code
  ) 
  ,cte1 as
  (
   select CodeStatus,code,
   row_number()over(partition by code order by StartDate desc) rn
   from table
 ) select cte.*,cte1.CodeStatus 
   from cte join cte1 on cte.code=cte1.code
   where cte1.rn=1

答案 2 :(得分:0)

要从发布的样本数据中获得发布的预期结果,可以使用条件聚合。即如果状态为有效,则仅将日期传递到min()max()。这样,您将获得最大和最小。要获取当前状态,请检查当前时间是在开始时间之后还是在开始时间之后以及结束时间之前。如果通过,则将状态传递给例如max()

SELECT code,
       to_char(min(CASE
                    WHEN codestatus = 'Active' THEN
                      startdate
                   END), 'YYYYMMDD') startdate,
       to_char(min(CASE
                    WHEN codestatus = 'Active' THEN
                      enddate
                   END), 'YYYYMMDD') enddate,
       max(CASE
             WHEN startdate <= sysdate
                  AND enddate > sysdate THEN
               codestatus
           END) status
       FROM elbat
       GROUP BY code
       ORDER BY code;

db<>fiddle

但是我怀疑可能还有更多。如果活动期间多于一个期间怎么办?采用最早的开始和最新的开始是否正确?如果还有更多时间与当前时间匹配,那一个会决定当前状态怎么办?

答案 3 :(得分:0)

您可以使用类似的方法获取代码的开始日期和结束日期以及当前状态。性能取决于您将WITH部分中的选择限制为代码还是日期。

 WITH CodeDates AS 
 (
   select 
       code,
       min(StartDate)  startdate,
       max(EndDate)    enddate
     from table
    Group by code
 )
  Select c.code,
         c.startdate
         c.enddate,
         t.codestatus
   From CodeDates c
   Join table  t
     on t.code = c.code
     and t.enddate = c.enddate