根据postgreSQL中的条件获取下3行或相邻行

时间:2018-08-28 05:01:24

标签: sql postgresql

我有一个超过10,000行的数据库。例如:

id text 
1  abc
2  ghj
3  cde
4  hif
5  klm
6  bbc
7  jkl
8  mno
9  dbo
10 ijk

我需要获取文本符合条件的以下三行。

例如:如果我正在执行'%bc%查询之类的文本,则应返回ID为1,2,3,4,6,7,8,9的行,因为第1行和第6行是匹配项

4 个答案:

答案 0 :(得分:0)

使用以下查询获得所需的结果。我假设您只想根据ID计算下一个,并且ID总是以1递增,就像您提到的那样。

如果ID并不总是增加1,则首先添加一个ROW Number,然后在t2子查询中替换id,并用行号替换连接条件。

select t1.id, t1.id_text 
from test t1
join
(
select id from test where id_text like '%bc%'
UNION
select id+1 from test where id_text like '%bc%'
UNION
select id+2 from test where id_text like '%bc%'
UNION
select id+3 from test where id_text like '%bc%'
) t2
on t1.id = t2.id;

SQL Fiddle Link

答案 1 :(得分:0)

with -- Test data
  t(i, x) as (values
    (1,'abc'),(2,'ghj'),(3,'cde'),(4,'hif'),(5,'klm'),(6,'bbc'),(7,'jkl'),(8,'mno'),(9,'dbo'),(10,'ijk'))
select r.*
from
  t as t0 cross join lateral (
    select *
    from t
    where t.i >= t0.i
    order by t.i
    limit 4) as r
where t0.x like '%bc%'
order by r.i;

Lateral joins允许在下一个子查询中使用上一个表。

答案 2 :(得分:0)

您可以使用类似这样的内容:

SELECT next.*
FROM test, test next
WHERE test.text LIKE '%bc%'
  AND (test.id + 1 = next.id OR test.id + 2 = next.id OR test.id + 3 = next.id)

答案 3 :(得分:0)

我不会假设id之间没有空格。一种方法使用lag()

select t.*
from (select t.*,
             lag(text) over (order by id) as prev_text,
             lag(text, 2) over (order by id) as prev_text2,
             lag(text, 3) over (order by id) as prev_text3
      from t
     ) t
where text like '%bc%' or
      prev_text like '%bc%' or
      prev_text2 like '%bc%' or
      prev_text3 like '%bc%';

您还可以使用其他窗口功能进行一次比较:

select id, text
from (select t.*,
             sum( (text like '%bc%')::int ) over (order by id rows between 3 preceding and current row) as cnt
      from t
     ) t
where cnt > 0;

使用id上的索引,这可能是解决问题的最快方法。