我有下面提到的数据。我希望得到开始消息的min和相应的成功消息。如果没有启动或成功消息,则它应显示为null。
启动消息表:
ID1 Timestamp_start_msg_recieved date jobid message time in seconds
1234 5/14/2014 10:02:29 5/14/2014 abc start 262
1234 5/14/2014 10:02:31 5/14/2014 abc start 264
1234 5/14/2014 10:02:45 5/14/2014 abc start 278
1234 5/14/2014 10:02:50 5/14/2014 abc start 285
1234 5/14/2014 10:09:04 5/14/2014 abc start 165
1234 5/14/2014 10:09:06 5/14/2014 abc start 2167
1234 5/14/2014 10:09:16 5/14/2014 abc start 2180
1234 5/14/2014 10:09:26 5/14/2014 abc start 2190
1234 5/14/2014 11:45:11 5/14/2014 abc start 8767
1234 5/14/2014 16:48:20 5/14/2014 abc start 878
1234 5/14/2014 19:02:52 5/14/2014 abc start 687
5678 5/14/2014 22:02:52 5/14/2014 pqr start 501
5678 5/14/2014 23:10:40 5/14/2014 abcd start 200
成功消息表:
ID1 Timestamp_success_msg_recieved date jobid message time in seconds
1234 5/14/2014 10:02:52 5/14/2014 abc successful 290
1234 5/14/2014 10:09:32 5/14/2014 abc successful 4280
1234 5/14/2014 11:45:15 5/14/2014 abc successful 8774
1234 5/14/2014 11:45:18 5/14/2014 abc successful 8777
1234 5/14/2014 11:45:19 5/14/2014 abc successful 8778
1234 5/14/2014 11:45:25 5/14/2014 abc successful 8784
1234 5/14/2014 16:48:22 5/14/2014 abc successful 880
1234 5/14/2014 19:03:00 5/14/2014 abc successful 699
5678 5/14/2014 22:03:00 5/14/2014 pqr successful 250
5678 5/19/2014 14:00:16 5/19/2014 pqr successful 400
预期结果:
ID1 IMESTAMP_for_start_message TIMESTAMP_for_success_message Date Jobid msg msg start_secs success_secs
1234 5/14/2014 10:02:29 5/14/2014 10:02:52 5/14/2014 abc start success 262 290
1234 5/14/2014 10:09:04 5/14/2014 10:09:32 5/14/2014 abc start success 165 4280
1234 5/14/2014 11:45:11 5/14/2014 11:45:25 5/14/2014 abc start success 8767 8784
1234 5/14/2014 16:48:20 5/14/2014 16:48:22 5/14/2014 abc start success 878 880
1234 5/14/2014 19:02:52 5/14/2014 19:03:00 5/14/2014 abc start success 687 699
5678 5/14/2014 22:02:52 5/14/2014 22:03:00 5/14/2014 pqr start success 501 699
5678 5/14/2014 23:10:40 null 5/14/2014 abcd start success 250 null
5678 null 5/19/2014 14:00:16 5/19/2014 pqr null success null 400
我正在尝试将start_timestamp的Min与下一个与id1和jobid相对应的success_timestamp的Min结合起来。如果给定的id1和jobid有一个启动消息列表并且没有成功消息,那么它应该显示NULL并且反之亦然。使用WITH子句尝试使用临时表,也使用自连接方法。下面是我的查询,但WITH子句查询返回表中整体数据的MIN。
注意:TIME IN SECONDS具有随机值而非实际数据。
使用的查询:
WITH DATA AS
(SELECT MIN(smt.column13) timestamp_for_success_message
FROM success_table1 smt, start_table2 b
WHERE
(SMT.id1 = b.id1)
AND (SMT.jobid = b.jobid)
AND (SMT.timestamp_for_success_message_recieved >= b.timestamp_for_start_message_recieved)
)
SELECT distinct a.timestamp_for_success_message_recieved,
b.timestamp_for_start_message_recieved,
b.id1,
b.jobid
FROM data a,
start_table2 b
order by b.timestamp_start_message_recieved, a.timestamp_for_success_message_recieved, b.jobid, b.id1;
答案 0 :(得分:0)
select nvl(a.ID1,b.ID1) ID1 , start_timestamp , success_timestamp
from
(select ID1 , min(timestamp) start_timestamp
from Start_Message_Table
group by ID1) a
full outer join
(select ID1 , min(timestamp) success_timestamp
from Success_Message_Table
group by ID1) b
on a.ID1 = b.ID1;
希望,我清楚地理解这个问题。尝试使用上面的查询。如果内部查询中需要任何额外的列,请添加。
答案 1 :(得分:0)
我对这个问题的理解是,起始表中的每一行代表某种起始作业。成功表表示完成工作。要找出作业何时完成,您需要在success表中找到与id1和jobid列匹配的行,其中最短的时间戳大于起始行时间戳,除非start表中的前一行与成功匹配行。
例如,start表中的第一行与success表中的第一行匹配,但start表中的第二行在success表中没有匹配。
为了解决这个问题,我使用了嵌套的子查询来构建所需的每一段数据。
SELECT start.id1, start.jobid, start.TIMESTAMP_START_MSG_RECIEVED AS start, table2.end
FROM start
LEFT OUTER JOIN (
SELECT table1.id1, table1.jobid, MIN(table1.start) AS start, table1.end
FROM (
SELECT s.id1, s.jobid, s.TIMESTAMP_START_MSG_RECIEVED AS start, MIN(t.TIMESTAMP_SUCCESS_MSG_RECIEVED) AS end
FROM start AS s
LEFT OUTER JOIN success AS t ON t.id1 = s.id1 AND t.jobid = s.jobid AND t.TIMESTAMP_SUCCESS_MSG_RECIEVED >= s.TIMESTAMP_START_MSG_RECIEVED
GROUP BY s.id1, s.TIMESTAMP_START_MSG_RECIEVED, s.jobid, s.time
ORDER BY start) AS table1
GROUP BY table1.id1, table1.jobid, table1.end
ORDER BY table1.end) AS table2 ON table2.id1 = start.id1 AND table2.jobid = start.jobid AND table2.start = start.TIMESTAMP_START_MSG_RECIEVED
ORDER BY start
最里面的select从成功表中获取每个开始行和最低结束时间。
然后,下一个select从table1获取具有最低开始时间的行 然后,外部选择将起始表与表2连接,以包括尚未完成的所有作业。
答案 2 :(得分:0)
此解决方案不是单一查询,它需要为结果和运行过程创建表。我认为用递归查询解决这个问题是可能的,但我没有设法创建一个。
程序未经过优化,可能在大数据集上速度较慢,但......它可以正常工作。
还有一件事 - 我不确定 TIME IN SECONDS有什么随机值而不是实际数据意味着什么。你的结果表明,你只是忽略计算中的秒数,但是希望它们在结果中,所以我重建了代码(由于所有这些trunc
和其他因素,可能会减慢因素)。另外 - 如果您将主键添加到表格中会更容易。
创建表,运行程序和获取结果的代码:
create table table_pairs as
select ts.ID1, ts.TIME_START, te.TIME_END, ts.tdate,
ts.JOBID, ts.MSG msg_start, te.MSG msg_end,
cast(null as timestamp) time_start_max
from table_start ts, table_end te
where 1=0;
begin p_pairs; end;
select id1, to_char(time_start, 'yyyy-MM-dd HH24:mi:ss') time_start,
to_char(time_end, 'yyyy-MM-dd HH24:mi:ss') time_end,
tdate, jobid, msg_start, msg_end
--, to_char(time_start_max, 'yyyy-MM-dd HH24:mi:ss') time_start_max
from table_pairs
order by id1, time_start, time_end, jobid;
结果:
id1 time_start time_end tdate jobid msg_start msg_end
---- ------------------- ------------------- ---------- ----- ------------ ----------------
1234 2014-05-14 10:02:29 2014-05-14 10:02:52 2014-05-14 abc start 262 successful 290
1234 2014-05-14 10:09:04 2014-05-14 10:09:32 2014-05-14 abc start 165 successful 4280
1234 2014-05-14 11:45:11 2014-05-14 11:45:25 2014-05-14 abc start 8767 successful 8784
1234 2014-05-14 16:48:20 2014-05-14 16:48:22 2014-05-14 abc start 878 successful 880
1234 2014-05-14 19:02:52 2014-05-14 19:03:00 2014-05-14 abc start 687 successful 699
5678 2014-05-14 22:02:52 2014-05-14 22:03:00 2014-05-14 pqr start 501 successful 250
5678 2014-05-14 23:10:40 2014-05-14 abcd start 200
5678 2014-05-19 14:00:16 2014-05-14 pqr successful 400
步骤:
create or replace procedure p_pairs is
r_start table_start%rowtype;
r_pair table_pairs%rowtype;
v_start_min table_pairs.time_start%type;
v_start_max table_pairs.time_start_max%type;
cursor c_success is
select * from table_pairs order by id1, jobid, time_end for update;
begin
begin -- delete everything from w_pairs and insert all ended processes
delete from table_pairs;
--simple version with proper seconds handling
--insert into table_pairs (id1, jobid, tdate, time_end, msg_end)
-- (select id1, jobid, tdate, time_end, msg from table_end);
-- complicated version for seconds ignored
insert into table_pairs (id1, jobid, tdate, time_end, msg_end)
(select id1, jobid, tdate, max(time_end), max(msg)
from (
select id1, jobid, tdate, time_end,
last_value(msg) over (partition by id1, jobid, tdate, trunc(time_end, 'mi')
order by null rows between unbounded preceding and unbounded following) msg
from table_end)
group by id1, jobid, tdate, trunc(time_end, 'mi')
);
end;
for r_pair in c_success
loop
begin -- find matching starting process
select min(time_start), max(time_start) into v_start_min, v_start_max
from (
select * from table_start ts1
where ts1.id1 = r_pair.id1 and ts1.jobid = r_pair.jobid
and trunc(ts1.time_start, 'mi') <= trunc(r_pair.time_end, 'mi')
minus -- eliminate already "used" processes
select * from table_start ts2
where ts2.jobid = r_pair.jobid
and trunc(ts2.time_start, 'mi') <= (
select trunc(max(time_start_max), 'mi') from table_pairs
where table_pairs.jobid = r_pair.jobid and table_pairs.id1=r_pair.id1
)
);
select * into r_start
from (
select * from table_start ts
where ts.jobid = r_pair.jobid and ts.id1 = r_pair.id1
and trunc(time_start,'mi') <= trunc(r_pair.time_end, 'mi')
and trunc(ts.time_start, 'mi') = trunc(v_start_min, 'mi')
order by time_start
)
where rownum = 1;
update table_pairs set
tdate = r_start.tdate,
time_start = v_start_min,
time_start_max = v_start_max,
msg_start = r_start.msg
where current of c_success;
exception when no_data_found then
null; -- no matching starting process
end;
end loop;
begin -- add started and not finished processes
insert into table_pairs (id1, jobid, time_start, tdate, msg_start)
select id1, jobid, time_start, tdate, msg
from (
select * from table_start
minus
select ts.*
from table_start ts
join table_pairs tp
on ts.jobid = tp.jobid and ts.id1=tp.id1
and trunc(ts.time_start, 'mi')
between trunc(tp.time_start, 'mi') and trunc(tp.time_start_max, 'mi')
);
end;
end p_pairs;
输入数据准备:
create table TABLE_START
(
ID1 NUMBER,
TIME_START TIMESTAMP(6),
TDATE DATE,
JOBID VARCHAR2(10),
MSG VARCHAR2(20)
);
insert into table_start
select 1234, to_date('05/14/2014 10:02:29', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 262' from dual
union all select 1234, to_date('05/14/2014 10:02:31', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 264' from dual
union all select 1234, to_date('05/14/2014 10:02:45', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 278' from dual
union all select 1234, to_date('05/14/2014 10:02:50', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 285' from dual
union all select 1234, to_date('05/14/2014 10:09:04', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 165' from dual
union all select 1234, to_date('05/14/2014 10:09:06', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 2167' from dual
union all select 1234, to_date('05/14/2014 10:09:16', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 2180' from dual
union all select 1234, to_date('05/14/2014 10:09:26', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 2190' from dual
union all select 1234, to_date('05/14/2014 11:45:11', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 8767' from dual
union all select 1234, to_date('05/14/2014 16:48:20', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 878' from dual
union all select 1234, to_date('05/14/2014 19:02:52', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'start 687' from dual
union all select 5678, to_date('05/14/2014 22:02:52', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'pqr', 'start 501' from dual
union all select 5678, to_date('05/14/2014 23:10:40', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abcd', 'start 200' from dual
create table TABLE_END
(
ID1 NUMBER,
TIME_END TIMESTAMP(6),
TDATE DATE,
JOBID VARCHAR2(10),
MSG VARCHAR2(20)
);
insert into table_end
select 1234, to_date('05/14/2014 10:02:52', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 290' from dual
union all select 1234, to_date('05/14/2014 10:09:32', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 4280' from dual
union all select 1234, to_date('05/14/2014 11:45:15', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 8774' from dual
union all select 1234, to_date('05/14/2014 11:45:18', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 8777' from dual
union all select 1234, to_date('05/14/2014 11:45:19', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 8778' from dual
union all select 1234, to_date('05/14/2014 11:45:25', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 8784' from dual
union all select 1234, to_date('05/14/2014 16:48:22', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 880' from dual
union all select 1234, to_date('05/14/2014 19:03:00', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'abc', 'successful 699' from dual
union all select 5678, to_date('05/14/2014 22:03:00', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'pqr', 'successful 250' from dual
union all select 5678, to_date('05/19/2014 14:00:16', 'MM/DD/YYYY HH24:mi:ss'), to_date('05/14/2014', 'MM/DD/YYYY'), 'pqr', 'successful 400' from dual