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

问题描述 投票:-1回答:4

我有以下数据

+------+-----------+----------+-------+------------+
| 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来提取数据,因此性能也很重要。

有人可以帮我查询。

sql oracle
4个回答
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

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


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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.