我有以下数据显示支持通知单的状态:
更简洁通用的示例:
STATUS SEQ_NO
New 1
Open 2
Open 3
Open 4
Queued 5
Open 6
Open 7
Open 8
Completed 9
Completed 10
Completed 11
Closed 12
我要从中提取记录
STATUS SEQ_NO
New 1
Open 2
Queued 5
Open 6
Completed 9
Closed 12
-- SELECT status, start_time FROM events_tab ORDER BY start_time;
STATUS START_TIME
New 30/09/2014 3:48:10 PM -- I want this record,
Open 30/09/2014 3:48:10 PM -- and this,
Open 1/10/2014 10:41:57 AM
Open 4/03/2015 9:59:04 AM
Queued 18/06/2015 1:31:30 PM -- and this,
Open 20/06/2015 10:10:47 PM -- and this,
Open 20/06/2015 11:20:11 PM
Open 27/06/2015 1:18:50 PM
Completed 27/06/2015 1:22:08 PM -- and this,
Completed 28/09/2015 9:31:55 AM
Completed 5/10/2015 11:57:38 AM
Closed 11/01/2016 9:31:26 AM -- and this.
这些是在每个州发生的事件。我想据此制定状态变更的时间表。
我要压缩这些记录,以便仅显示组的第一行。但是,请注意,实际上有两组Open
状态。因此,我应该获得状态为Open
的两条记录。
基本上我想要以下结果:
STATUS START_TIME
New 30/09/2014 3:48:10 PM
Open 30/09/2014 3:48:10 PM
Queued 18/06/2015 1:31:30 PM
Open 20/06/2015 10:10:47 PM
Completed 27/06/2015 1:22:08 PM
Closed 11/01/2016 9:31:26 AM
如何使用SQL语句实现这一目标?
我尝试过
SELECT status, MIN(start_time)
FROM events_tab
GROUP BY status;
但是,如上所述,这不包括处于Open
状态的多个记录。
答案 0 :(得分:2)
您可以使用Tabibitosan技术来实现此目标:
WITH your_table AS (SELECT 'New' status, to_date('30/09/2014 03:48:10 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Open' status, to_date('30/09/2014 03:48:10 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Open' status, to_date('1/10/2014 10:41:57 AM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Open' status, to_date('4/03/2015 09:59:04 AM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Queued' status, to_date('18/06/2015 01:31:30 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Open' status, to_date('20/06/2015 10:10:47 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Open' status, to_date('20/06/2015 11:20:11 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Open' status, to_date('27/06/2015 01:18:50 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Completed' status, to_date('27/06/2015 01:22:08 PM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Completed' status, to_date('28/09/2015 09:31:55 AM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Completed' status, to_date('5/10/2015 11:57:38 AM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual UNION ALL
SELECT 'Closed' status, to_date('11/01/2016 09:31:26 AM', 'dd/mm/yyyy hh:mi:ss AM') start_time FROM dual)
SELECT status,
MIN(start_time) start_time
FROM (SELECT status,
start_time,
row_number() OVER (ORDER BY start_time, status) - row_number() OVER (PARTITION BY status ORDER BY start_time, status) grp
FROM your_table)
GROUP BY status, grp
ORDER BY start_time, status;
STATUS START_TIME
--------- -------------------
New 30/09/2014 15:48:10
Open 30/09/2014 15:48:10
Queued 18/06/2015 13:31:30
Open 20/06/2015 22:10:47
Completed 27/06/2015 13:22:08
Closed 11/01/2016 09:31:26
由于您的行具有不同的状态且具有相同的start_time,因此我将状态添加到了by中,以便获得您想要的结果。我不知道那是错字,还是多行确实可以有相同的日期。
此外,我假设您的示例中的数据涉及一个“事物”,但是在您的真实表中,您可以具有多个“事物”,每个“事物”都具有自己的一组状态等。
在这种情况下,您需要将用于区分“事物”(例如,id或event_name等)的列添加到两个row_number()
分析函数中。 (例如row_number() over (partition by <thing column(s)> order by start_time, status)
)
答案 1 :(得分:1)
您也可以尝试SQL for Pattern Matching
WITH tickets(STATUS, START_TIME) AS (
SELECT 'New', TO_DATE('30/09/2014 3:48:10 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Open', TO_DATE('30/09/2014 3:48:10 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Open', TO_DATE('1/10/2014 10:41:57 AM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Open', TO_DATE('4/03/2015 9:59:04 AM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Queued', TO_DATE('18/06/2015 1:31:30 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Open', TO_DATE('20/06/2015 10:10:47 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Open', TO_DATE('20/06/2015 11:20:11 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Open', TO_DATE('27/06/2015 1:18:50 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Completed', TO_DATE('27/06/2015 1:22:08 PM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Completed', TO_DATE('28/09/2015 9:31:55 AM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Completed', TO_DATE('5/10/2015 11:57:38 AM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual UNION ALL
SELECT 'Closed', TO_DATE('11/01/2016 9:31:26 AM', 'dd/mm/yyyy hh:mi:ss AM') FROM dual)
SELECT STATUS, START_TIME
FROM tickets
MATCH_RECOGNIZE (
ORDER BY START_TIME
MEASURES
START_TIME AS START_TIME,
STATUS as STATUS
PATTERN ( CHNG )
DEFINE
CHNG AS CHNG.STATUS <> PREV(CHNG.STATUS) OR PREV(CHNG.STATUS) IS NULL
)
STATUS START_TIME
========== ====================
New 30.09.2014 15:48:10
Open 30.09.2014 15:48:10
Queued 18.06.2015 13:31:30
Open 20.06.2015 22:10:47
Completed 27.06.2015 13:22:08
Closed 11.01.2016 09:31:26
CHNG.STATUS <> PREV(CHNG.STATUS)
匹配STATUS
与上一行不同的每一行。 PREV(CHNG.STATUS) IS NULL
用于获得第一行。
答案 2 :(得分:0)
根据需要使用LAG功能跟踪状态变化:
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=38a991b698c858f6f0417c7d4c0dc9d3
with cte1 (st,dt) as
(
select 'New' as st, '30/09/2014 3:48:10 PM' as dt from dual
union all
select 'Open' as st, '30/09/2014 3:48:10 PM' as dt from dual
union all
select 'Open' as st, '20/09/2014 3:48:10 PM' as dt from dual
union all
select 'Qued' as st, '18/06/2015 1:31:30' as dt from dual
)
select st, min(case when st<>prev_order_date then dt else dt end) as d
from
(
SELECT st, dt,
LAG (st,1) OVER (ORDER BY st) AS prev_order_date
FROM cte1
)a
group by st
答案 3 :(得分:0)
使用row_number
窗口功能
select STATUS ,START_TIME from
(
select STATUS,START_TIME,
row_number() over (partition by STATUS,EXTRACT(YEAR FROM START_TIME) order by START_TIME) rn
from events_tab
) t where rn=1