试图查找Oracle SQL中状态字段已更改的最近日期
我有一个表格,显示了位置ID的LOCN_ID的完整历史记录,其中包括一个ACTIVE_状态字段,显示a表示ACTIVE,或I表示inactive。每次位置的活动状态更改时,都会创建一条新记录,其中包含一个新的OP_日期。但是,每当表中的外部可见字段发生更改时,也会创建另一条具有新操作日期的记录 对于表中的每个LOCN_ID,我需要能够找到ACTIVE_STATUS字段更改为I或A的最新OP_日期。我不关心外部可视字段何时更改。对于示例中显示的LOCN_ID,结果应为:试图查找Oracle SQL中状态字段已更改的最近日期,sql,oracle,Sql,Oracle,我有一个表格,显示了位置ID的LOCN_ID的完整历史记录,其中包括一个ACTIVE_状态字段,显示a表示ACTIVE,或I表示inactive。每次位置的活动状态更改时,都会创建一条新记录,其中包含一个新的OP_日期。但是,每当表中的外部可见字段发生更改时,也会创建另一条具有新操作日期的记录 对于表中的每个LOCN_ID,我需要能够找到ACTIVE_STATUS字段更改为I或A的最新OP_日期。我不关心外部可视字段何时更改。对于示例中显示的LOCN_ID,结果应为: OP_DATE
OP_DATE LOCN_ID ACTIVE_STATUS
12/9/11 7:34 558732 I
在某些情况下,LOCN_ID的活动状态永远不会改变,在这种情况下,结果应该是该LOCN_ID最早的运行日期
如何在Oracle SQL中编写查询以显示每个LOCN\u ID的所需输出?您可以使用行号:
您可以使用行号:
我已使用LEFT JOIN为您创建了以下查询:
-- SAMPLE DATA
WITH DATAA (OP_DATE, LOCN_ID, ACTIVE_STATUS, EXTERNALLY_VISIBLE)
AS
(
SELECT TO_DATE('04/06/2013 2:31','MM/DD/RRRR HH24:MI'), 558732, 'I', 'Y' FROM DUAL UNION ALL
SELECT TO_DATE('12/09/2011 7:34','MM/DD/RRRR HH24:MI'), 558732, 'I', 'N' FROM DUAL UNION ALL
SELECT TO_DATE('10/02/2011 3:05','MM/DD/RRRR HH24:MI'), 558732, 'A', 'N' FROM DUAL UNION ALL
SELECT TO_DATE('10/02/2011 2:59','MM/DD/RRRR HH24:MI'), 558732, 'I', 'N' FROM DUAL UNION ALL
SELECT TO_DATE('10/02/2011 3:00','MM/DD/RRRR HH24:MI'), 558732, 'I', 'Y' FROM DUAL UNION ALL
SELECT TO_DATE('04/09/2011 2:18','MM/DD/RRRR HH24:MI'), 558732, 'A', 'Y' FROM DUAL
),
-- ACTUAL QUERY STARTS FROM HERE
CTE(OP_DATE, LOCN_ID, ACTIVE_STATUS, EXTERNALLY_VISIBLE, RN) AS (
SELECT
D.*,
ROW_NUMBER() OVER(
PARTITION BY LOCN_ID
ORDER BY
OP_DATE
) AS RN
FROM
DATAA D
)
SELECT
OP_DATE,
LOCN_ID,
ACTIVE_STATUS
FROM
(
SELECT
A.OP_DATE,
A.LOCN_ID,
A.ACTIVE_STATUS,
ROW_NUMBER() OVER(
PARTITION BY A.LOCN_ID
ORDER BY
A.OP_DATE DESC
) AS RN
FROM
CTE A
LEFT JOIN CTE B ON ( A.RN = B.RN + 1 )
WHERE
( A.ACTIVE_STATUS <> B.ACTIVE_STATUS
OR B.ACTIVE_STATUS IS NULL )
)
WHERE
RN = 1;
干杯 我使用LEFT JOIN为您创建了以下查询:
-- SAMPLE DATA
WITH DATAA (OP_DATE, LOCN_ID, ACTIVE_STATUS, EXTERNALLY_VISIBLE)
AS
(
SELECT TO_DATE('04/06/2013 2:31','MM/DD/RRRR HH24:MI'), 558732, 'I', 'Y' FROM DUAL UNION ALL
SELECT TO_DATE('12/09/2011 7:34','MM/DD/RRRR HH24:MI'), 558732, 'I', 'N' FROM DUAL UNION ALL
SELECT TO_DATE('10/02/2011 3:05','MM/DD/RRRR HH24:MI'), 558732, 'A', 'N' FROM DUAL UNION ALL
SELECT TO_DATE('10/02/2011 2:59','MM/DD/RRRR HH24:MI'), 558732, 'I', 'N' FROM DUAL UNION ALL
SELECT TO_DATE('10/02/2011 3:00','MM/DD/RRRR HH24:MI'), 558732, 'I', 'Y' FROM DUAL UNION ALL
SELECT TO_DATE('04/09/2011 2:18','MM/DD/RRRR HH24:MI'), 558732, 'A', 'Y' FROM DUAL
),
-- ACTUAL QUERY STARTS FROM HERE
CTE(OP_DATE, LOCN_ID, ACTIVE_STATUS, EXTERNALLY_VISIBLE, RN) AS (
SELECT
D.*,
ROW_NUMBER() OVER(
PARTITION BY LOCN_ID
ORDER BY
OP_DATE
) AS RN
FROM
DATAA D
)
SELECT
OP_DATE,
LOCN_ID,
ACTIVE_STATUS
FROM
(
SELECT
A.OP_DATE,
A.LOCN_ID,
A.ACTIVE_STATUS,
ROW_NUMBER() OVER(
PARTITION BY A.LOCN_ID
ORDER BY
A.OP_DATE DESC
) AS RN
FROM
CTE A
LEFT JOIN CTE B ON ( A.RN = B.RN + 1 )
WHERE
( A.ACTIVE_STATUS <> B.ACTIVE_STATUS
OR B.ACTIVE_STATUS IS NULL )
)
WHERE
RN = 1;
干杯 您必须处理这两种情况,即状态发生变化的行和状态不存在的行。滞后是很明显的,因为它是为了找到以前的值而设计的。可选的是较旧、较慢的自连接。我们还需要行号,因为您有复杂的条件排序。在第一部分的行_编号中,我们需要降序,然后在状态没有变化的情况下升序。可以这样做:
select op_date, locn_id, active_status
from (
select a.*, row_number()
over (partition by locn_id
order by case when active_status <> las then sysdate-op_date end,
op_date) as rn
from (select t.*, lag(active_status) over (partition by locn_id order by op_date) las
from t) a)
where rn = 1
您必须处理两种情况,即状态发生变化的行和状态不存在的行。滞后是很明显的,因为它是为了找到以前的值而设计的。可选的是较旧、较慢的自连接。我们还需要行号,因为您有复杂的条件排序。在第一部分的行_编号中,我们需要降序,然后在状态没有变化的情况下升序。可以这样做:
select op_date, locn_id, active_status
from (
select a.*, row_number()
over (partition by locn_id
order by case when active_status <> las then sysdate-op_date end,
op_date) as rn
from (select t.*, lag(active_status) over (partition by locn_id order by op_date) las
from t) a)
where rn = 1
这将返回2013年6月4日作为OP_日期,因为该日期的外部可视字段从N更改为Y,活动_状态保持为I。我需要结果显示11年9月12日,因为这是活动_状态从A更改为I的最近日期。@JNegoda。我懂了。我修正了处理这个问题的答案。这返回4/6/13作为操作日期,因为外部可见字段在该日期从N变为Y,活动状态保持为I。我需要结果显示11年9月12日,因为这是活动状态从A变为I的最近日期。@JNegoda。我懂了。我解决了这个问题。