我有一张表格
select rowid,* from t;
rowid f
----- -----
1 aaa
2 bbb
3 ccc
4 ddd
5 eee
6 fff
7 ggg
8 aaa
9 bbb
10 ccc
11 ddd
12 eee
13 fff
14 ggg
我想在给定的行匹配之前选择n行和m行,例如对于匹配f ='ccc'且n = m = 1的行我想要
2 bbb
3 ccc
4 ddd
9 bbb
10 ccc
11 ddd
rowid在我的设置中是连续的,所以我想我们可以玩它。我尝试了
这一行select rowid,f from t where rowid between
(select rowid-1 from t where f='ccc') and
(select rowid+1 from t where f='ccc');
rowid f
----- -----
2 bbb
3 ccc
4 ddd
但结果显然是错误的,我只得到了'ccc'比赛的第一次出现。我想我要加入或者可能是递归cte,但我很害怕它是迄今为止我的知识分子:) Thanx提前。
答案 0 :(得分:1)
scalar subquery只能返回一个值。
你可以做两个自连接,但使用set操作会更简单:
SELECT * FROM t
WHERE rowid IN (SELECT rowid - 1 FROM t WHERE f = 'ccc'
UNION ALL
SELECT rowid FROM t WHERE f = 'ccc'
UNION ALL
SELECT rowid + 1 FROM t WHERE f = 'ccc');
n
和m
的较大值需要更多子查询。
如果太多,您可以使用联接:
SELECT *
FROM t
WHERE rowid IN (SELECT t.rowid
FROM t
JOIN (SELECT rowid - ? AS n,
rowid + ? AS m
FROM t
WHERE f = 'ccc'
) AS ranges
ON t.rowid BETWEEN ranges.n AND ranges.m);
答案 1 :(得分:0)
我提出了一个不是最优的解决方案,但我无法简化(删除)临时(中间)表。
select rowid,f from t;
rowid f
----- -----
1 aaa
2 bbb
3 ccc
4 ddd
5 eee
6 fff
7 ggg
8 aaa
9 bbb
10 ccc
11 ddd
12 eee
13 fff
14 ggg
create table u as
select t2.rowid x,t1.rowid+2 y from t t1 // +2 ==> 2 rows after 'ccc'
join t t2 on t1.rowid=t2.rowid+1 // +1 ==> 1 row before 'ccc'
where t1.f='ccc';
select * from u;
x y
----- -----
2 5
9 12
select t.rowid,t.f from t inner
join u on t.rowid>=u.x and t.rowid<=u.y'
rowid f
----- -----
2 bbb 1 before
3 ccc <== match
4 ddd 2 after
5 eee
9 bbb 1 before
10 ccc <== match
11 ddd 2 after
12 eee
我认为我已经满足了我的需求,但是优化非常好:)