Oracle sql中状态为T的上次更改数据
我的数据如下 在下面的示例中,最新记录为T,T的最后一次出现时间为2017年4月3日,因此需要显示行Oracle sql中状态为T的上次更改数据,sql,oracle,Sql,Oracle,我的数据如下 在下面的示例中,最新记录为T,T的最后一次出现时间为2017年4月3日,因此需要显示行 EMP EFFDT STATUS 11367 15-Apr-15 A 11367 14-Jun-15 A 11367 10-Aug-15 T 11367 2-Apr-17 A 11367 3-Apr-17 T * 11367 10-Apr-17 T 在以下示例中,最新记录为T,T的最后一次出现时间为2018年2月23日,因此需
EMP EFFDT STATUS
11367 15-Apr-15 A
11367 14-Jun-15 A
11367 10-Aug-15 T
11367 2-Apr-17 A
11367 3-Apr-17 T *
11367 10-Apr-17 T
在以下示例中,最新记录为T,T的最后一次出现时间为2018年2月23日,因此需要显示行
EMP EFFDT STATUS
20612 4-Sep-16 A
20612 23-Feb-18 T *
20612 20-Jul-18 T
在下面的示例中,最新记录有T,这是唯一出现的记录,因此请显示它
EMP EFFDT STATUS
20644 12-Jul-15 A
20644 8-Aug-16 A
20644 6-Oct-16 T*
在下面的示例中,最新记录没有T,因此不需要显示
EMP EFFDT STATUS
21155 18-May-17 T
21155 21-Jun-17 A
21155 13-Mar-18 T
21155 15-Aug-18 A
我想要的输出应该是*标记的记录
EMP EFFDT STATUS
11367 3-Apr-17 T
20612 23-Feb-18 T
20644 6-Oct-16 T
这是一个孤岛和缺口问题 在cte中,您试图找出上次更新T=0时,哪个岛有T 对于调试,您可以尝试
SELECT *
FROM cte
查看t值是如何创建的
WITH cte1
AS (
SELECT A.*
,lag(STATUS, 1, 0) OVER (
PARTITION BY EMP ORDER BY EFFDT
) AS PRIOR_STATUS
FROM Table1 A
)
SELECT EMP
,STATUS
,MAX(EFFDT) AS EFFDT
FROM cte1 A
WHERE A.STATUS = 'T'
AND A.PRIOR_STATUS <> 'T'
GROUP BY EMP
,STATUS
SQL Fiddle在此:
解决方案包括with条款中的模拟数据:
说明:
在子查询中,我们向输入数据添加了两列。列RN按EMPNO和STATUS给出每个分区内的排名,按EFFDT降序排列。LAST_STATUS使用LAST函数的分析版本将T或A指定为每个EMP的最后状态,并将此值附加到EMP的每一行,而不管每一行的自身状态如何
在外部查询中,我们只想保留最后状态为T的EMP。对于这些行,我们只想保留实际状态为T的行。顺便说一下,这将始终包括该EMP的最后一行,并且它的RN=1。此外,我们只对RN为1或可能为2的行感兴趣,如果该EMP至少有两行状态为T。对于给定的EMP,在状态为T的一行或两行中,我们希望得到最早的日期。如果该分区没有RN=2的行,则这将是唯一的日期;否则,它将是前一行的日期,RN=2
在外部选择中,我们选择EMP、最早日期和我们已经知道的状态,它是T,因此我们不需要为此做任何工作-实际上,不清楚为什么需要第三列,因为事先知道所有行中都是T。假设A和T是唯一的状态,这应该可以工作
WITH cte1
AS (
SELECT A.EMP, A.EFFDT, A.STATUS
,min(STATUS) OVER (
PARTITION BY EMP ORDER BY EFFDT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS MIN_STATUS
FROM Table1 A
)
SELECT
cte1.EMP
,MIN(cte1.EFFDT) AS EFFDT
,MIN(cte1.STATUS) as STATUS
FROM cte1
WHERE cte1.MIN_STATUS = 'T'
GROUP BY EMP
编辑:好吧,如果你有另一个雕像,让我们让它更坚固。事实上,这和胡安·卡洛斯·奥罗佩扎提议的差不多,但他错过了当前一排和无限下一部分之间的距离
哦,这是相同的解决方案:胡安·卡洛斯·奥罗佩扎(juan carlos oropeza)使用了描述无界跟随的顺序
with emp_status_log (EMP, EFFDT, STATUS) as
(
select 11367, to_date('15-Apr-15', 'dd-Mon-yy'), 'A' from dual union all
select 11367, to_date('14-Jun-15', 'dd-Mon-yy'), 'A' from dual union all
select 11367, to_date('10-Aug-15', 'dd-Mon-yy'), 'T' from dual union all
select 11367, to_date( '2-Apr-17', 'dd-Mon-yy'), 'A' from dual union all
select 11367, to_date( '3-Apr-17', 'dd-Mon-yy'), 'T' from dual union all
select 11367, to_date('10-Apr-17', 'dd-Mon-yy'), 'T' from dual union all
select 20612, to_date( '4-Sep-16', 'dd-Mon-yy'), 'A' from dual union all
select 20612, to_date('23-Feb-18', 'dd-Mon-yy'), 'T' from dual union all
select 20612, to_date('20-Jul-18', 'dd-Mon-yy'), 'T' from dual union all
select 20644, to_date('12-Jul-15', 'dd-Mon-yy'), 'A' from dual union all
select 20644, to_date( '8-Aug-16', 'dd-Mon-yy'), 'A' from dual union all
select 20644, to_date( '6-Oct-16', 'dd-Mon-yy'), 'T' from dual union all
select 21155, to_date('18-May-17', 'dd-Mon-yy'), 'T' from dual union all
select 21155, to_date('21-Jun-17', 'dd-Mon-yy'), 'A' from dual union all
select 21155, to_date('13-Mar-18', 'dd-Mon-yy'), 'T' from dual union all
select 21155, to_date('15-Aug-18', 'dd-Mon-yy'), 'A' from dual
)
,
-- End of simulated data (for testing only).
/* SQL query (solution) begins BELOW THIS LINE.
with--*/
cte1 as
(
select sl.*
,sum(decode(sl.STATUS, 'T', 0, 1)) OVER (
PARTITION BY sl.EMP ORDER BY sl.EFFDT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS non_t_count
from emp_status_log sl
)
select
cte1.emp
, min(cte1.effdt) as effdt
, min(cte1.status) as status
from cte1
where cte1.non_t_count = 0
group by cte1.emp
那么您希望前一行在最后一个T之前,或者如果只有一个,则最后一个T?如果EMP没有T怎么办?对于EMP,如果最新的EFFDT记录有“T”,则必须考虑它。如果最新的EFFDT不是T,则不需要。如果您看到第一个样本的最新EFFDT记录是T,但它实际上在2017年4月3日更新,第二个样本的最新记录是T,但它实际上在2018年2月23日更新,第三个样本的最新记录是T,这是英语的唯一更新,不是我的第一个冷瓜杰,可以吗将该案例包括在示例数据中。还包括欲望输出。实际上是在2017年4月3日更新的。你的意思是什么?我看到在2017年4月10日也有更新。我想你需要澄清更新是什么意思。你能按我的问题中所示显示输出吗?编辑解释了场景。这就是为什么我要求你包含欲望输出。作为你问题的一部分:@sryi刚刚添加了它,因为我对stackoverflow不熟悉,所以它对我来说花了很少的时间。请您将您的答案与所需的输出一起发布,请…完成,但如果您不能为自己这样做,则不确定您是否能够理解代码的其余部分。我不认为这是一个空白和孤岛问题;我认为OP的例子有误导性。在状态a,a,T,a,a,T中从最早到最新的顺序中,OP希望第三行的日期是T的第一次出现,然后紧接着是两个a,最后一个状态是T。他用文字解释的是,如果最后一个状态是T,如果有任何其他状态没有提到连续,他想要T的第二个最新状态。没有差距和岛屿,那么。我们还有其他状态,比如研发
alter session set nls_date_format = 'dd-Mon-rr';
with
simulated_data (EMP, EFFDT, STATUS) as (
select 11367, to_date('15-Apr-15'), 'A' from dual union all
select 11367, to_date('14-Jun-15'), 'A' from dual union all
select 11367, to_date('10-Aug-15'), 'T' from dual union all
select 11367, to_date( '2-Apr-17'), 'A' from dual union all
select 11367, to_date( '3-Apr-17'), 'T' from dual union all
select 11367, to_date('10-Apr-17'), 'T' from dual union all
select 20612, to_date( '4-Sep-16'), 'A' from dual union all
select 20612, to_date('23-Feb-18'), 'T' from dual union all
select 20612, to_date('20-Jul-18'), 'T' from dual union all
select 20644, to_date('12-Jul-15'), 'A' from dual union all
select 20644, to_date( '8-Aug-16'), 'A' from dual union all
select 20644, to_date( '6-Oct-16'), 'T' from dual union all
select 21155, to_date('18-May-17'), 'T' from dual union all
select 21155, to_date('21-Jun-17'), 'A' from dual union all
select 21155, to_date('13-Mar-18'), 'T' from dual union all
select 21155, to_date('15-Aug-18'), 'A' from dual
)
-- End of simulated data (for testing only).
-- SQL query (solution) begins BELOW THIS LINE.
select emp, min(effdt) as eff_dt, 'T' as status
from (
select emp, effdt, status,
row_number() over (partition by emp, status
order by effdt desc) as rn,
min(status) keep (dense_rank last order by effdt)
over (partition by emp) as last_status
from simulated_data
)
where last_status = 'T' and status = 'T' and rn <= 2
group by emp
;
EMP EFF_DT STATUS
---------- --------- ------
11367 03-Apr-17 T
20612 23-Feb-18 T
20644 06-Oct-16 T
WITH cte1
AS (
SELECT A.EMP, A.EFFDT, A.STATUS
,min(STATUS) OVER (
PARTITION BY EMP ORDER BY EFFDT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS MIN_STATUS
FROM Table1 A
)
SELECT
cte1.EMP
,MIN(cte1.EFFDT) AS EFFDT
,MIN(cte1.STATUS) as STATUS
FROM cte1
WHERE cte1.MIN_STATUS = 'T'
GROUP BY EMP
with emp_status_log (EMP, EFFDT, STATUS) as
(
select 11367, to_date('15-Apr-15', 'dd-Mon-yy'), 'A' from dual union all
select 11367, to_date('14-Jun-15', 'dd-Mon-yy'), 'A' from dual union all
select 11367, to_date('10-Aug-15', 'dd-Mon-yy'), 'T' from dual union all
select 11367, to_date( '2-Apr-17', 'dd-Mon-yy'), 'A' from dual union all
select 11367, to_date( '3-Apr-17', 'dd-Mon-yy'), 'T' from dual union all
select 11367, to_date('10-Apr-17', 'dd-Mon-yy'), 'T' from dual union all
select 20612, to_date( '4-Sep-16', 'dd-Mon-yy'), 'A' from dual union all
select 20612, to_date('23-Feb-18', 'dd-Mon-yy'), 'T' from dual union all
select 20612, to_date('20-Jul-18', 'dd-Mon-yy'), 'T' from dual union all
select 20644, to_date('12-Jul-15', 'dd-Mon-yy'), 'A' from dual union all
select 20644, to_date( '8-Aug-16', 'dd-Mon-yy'), 'A' from dual union all
select 20644, to_date( '6-Oct-16', 'dd-Mon-yy'), 'T' from dual union all
select 21155, to_date('18-May-17', 'dd-Mon-yy'), 'T' from dual union all
select 21155, to_date('21-Jun-17', 'dd-Mon-yy'), 'A' from dual union all
select 21155, to_date('13-Mar-18', 'dd-Mon-yy'), 'T' from dual union all
select 21155, to_date('15-Aug-18', 'dd-Mon-yy'), 'A' from dual
)
,
-- End of simulated data (for testing only).
/* SQL query (solution) begins BELOW THIS LINE.
with--*/
cte1 as
(
select sl.*
,sum(decode(sl.STATUS, 'T', 0, 1)) OVER (
PARTITION BY sl.EMP ORDER BY sl.EFFDT RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS non_t_count
from emp_status_log sl
)
select
cte1.emp
, min(cte1.effdt) as effdt
, min(cte1.status) as status
from cte1
where cte1.non_t_count = 0
group by cte1.emp