我们有一个项目,将数据写入日志记录表。现在,在调查问题时,查询问题行并获取周围的行会很有用,这样我们就可以轻松查看导致问题的原因。日志表有一个时间戳字段,所以我们可以按顺序排序。
基本上我想要SQL的“grep -C”。
举个例子,假设我们有一个reference_id列和一个activity_code列。我发现参考ID = 1234有问题,所以我想找到前面的N个活动。
编辑:一些示例数据
Code Reference Time
Allocate ABC1 9:00
Allocate ABC2 9:01
Problem MYREF1 9:02
Allocate ABC3 9:03
Allocate ABC4 9:03
Problem2 MYREF1 9:04
Allocate ABC5 9:09
我给了“MYREF1”作为值得关注的东西,但我希望看到同一时间发生的事情。我想要一个查询,它将获取“MYREF1”引用行,以及一些其他行(可能是周围或前面行中的1或2行)。在我的例子中,如果我想要前面的行(类似于grep -B1),那将是ABC2和ABC4
答案 0 :(得分:2)
这是一种方法的概念分解。
使用行号注释您订购的日志:
WITH ordered_logs AS (
SELECT ROWNUM r, log_table.*
FROM log_table
ORDER BY timestamp
)
SELECT * FROM ordered_logs;
查找我们正在寻找的中心信息的行号:
SELECT r r0 FROM ordered_logs
WHERE reference_id = 1234; -- or whatever uniquely identifies your problem
浏览它周围的几行:
SELECT * FROM ordered_logs, sought WHERE r BETWEEN r0 - 5 AND r0 + 5;
把它们全部重新组合在一起:
WITH
ordered_logs AS (
SELECT ROWNUM r, log_table.*
FROM log_table
ORDER BY timestamp
),
sought AS (
SELECT r r0
FROM ordered_logs
WHERE reference_id = 1234
)
SELECT *
FROM ordered_logs, sought
WHERE r BETWEEN r0 - 5 AND r0 + 5;
很多优化都是可能的,但这是我能找到的最简单的描述方式。
答案 1 :(得分:2)
有趣的问题。
您可以使用分析函数为您提供您可能感兴趣的时间范围,然后使用此范围从日志记录表中进行选择。
(没有机会运行这个SQL,但它应该给你这个想法)。
这给出了之前2行的TIME和之后的2行:
select
l.code,
l.reference,
l.time,
min(l.time) over (
order by l.time
rows between 2 preceding and current row)
preceding_time,
max(l.time) over (
order by l.time
rows beween current row and 2 following)
following_time
from
log_table l;
然后,您可以使用这些“时间框”在驾驶表中选择一个范围。
with timebox as
(
select
l.code,
l.reference,
l.time,
min(l.time) over (
order by l.time
rows between 2 preceding and current row)
preceding_time,
max(l.time) over (
order by l.time
rows beween current row and 2 following)
following_time
from
log_table l
)
select
*
from
log_table a
where
exists
(
select 1 from
timebox t
where
t.reference = 'MYREF1'
and a.time between t.preceding_time and t.following_time
);
那是否接近你所追求的目标?
答案 2 :(得分:0)
如果您只想要最新的:n行为1234:
select timestamp, activity_code
from
( select timestamp, activity_code
from log
where reference_id=1234
order by timestamp desc
)
where rownum <= :n;
答案 3 :(得分:0)
create table grep_like (
id number,
dt date,
txt varchar2(10)
);
insert into grep_like values(10, sysdate - 9/24/60/60, 'foo');
insert into grep_like values(30, sysdate - 8/24/60/60, 'bar');
insert into grep_like values(39, sysdate - 2/24/60/60, 'baz');
insert into grep_like values(22, sysdate - 5/24/60/60, '***');
insert into grep_like values(87, sysdate - 7/24/60/60, '###');
insert into grep_like values(57, sysdate - 4/24/60/60, '!!!');
insert into grep_like values(32, sysdate + 1/24/60/60, '---');
insert into grep_like values(99, sysdate - 12/24/60/60, '...');
insert into grep_like values(18, sysdate - 1/24/60/60, 'noo');
insert into grep_like values(20, sysdate - 10/24/60/60, 'moo');
insert into grep_like values(81, sysdate - 0/24/60/60, 'huh');
select p.dt, p.txt
from (
select r.dt, r.txt, r.r,
max(case when r.id = 57 then r.r else 0 end) over () p
from (
select dt, txt, id,
row_number() over (order by dt) r
from grep_like
) r
) p
where
p.r - p.p between -1 and 1
;
答案 4 :(得分:0)
另一种想法是以这样的方式抓住几分钟的条目:
WITH ts as (
SELECT timestamp
FROM log_table
WHERE reference_id = 1234)
SELECT *
FROM log_table join ts
WHERE timestamp > ts.timestamp - 5 minutes
AND timestamp < ts.timestamp + 5 minutes
当然,'+/- 5分钟'必须根据您的db-system实现。
这可能比获取rownumber并使用它来定义“窗口”要容易一些,但它可能无法满足您的要求。