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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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来提取数据,因此性能也很重要。

有人可以帮我查询。

答案

你只需要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
另一答案

您似乎想要代码处于活动状态的时间段和当前状态。这是一个带有扭曲的基本聚合查询:

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()函数。

另一答案

您可以使用类似的内容来获取开始和结束日期以及代码的当前状态。性能将取决于您将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
另一答案

要从您发布的样本数据中获得预期结果,您可以使用条件聚合。即如果状态有效,则仅将日期传递给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

但我怀疑可能还有更多。如果活跃期多于一个怎么办?从最早的开始到最新的结束是否正确?如果有更多的句点匹配当前时间,哪一个确定当前状态怎么办?

以上是关于Oracle查询以查找活动状态记录的开始和结束日期的主要内容,如果未能解决你的问题,请参考以下文章

尝试查找 Oracle SQL 中状态字段更改的最近日期

使用 Google BigQuery 上的开始/结束日期优化活动帐户查询

从日期中选择特定记录的 SQL 查询

oracle 如何查询两个时间段里的每一天数据之和。(只有开始日期和结束日期,没有每一天日期)

如何使用开始和结束日期时间在司机的行程中查找重叠记录

Oracle SQL 按日期查找唯一 ID