如何选择相邻行到任意行(在sql或postgresql中)?

Kzq*_*qai 18 sql postgresql selection

我想根据某些条件选择一些行,然后从该集合中取一个条目,在它之前和之后取5行.

现在,如果表上有一个主键,我可以用数字方式执行此操作(例如,主键在数字上比目标行的键小5,比目标行的键多5个).

因此,选择主键为7的行和附近的行:

select primary_key from table where primary_key > (7-5) order by primary_key limit 11;

2
3
4
5
6
-=7=-
8
9
10
11
12
Run Code Online (Sandbox Code Playgroud)

但是如果我只选择某些行开头,我会失去使用主键的数字方法(并且假设键无论如何都没有任何顺序),并且需要另一种方法来获取最接近的行在一定的目标行之后.

这种选择的主键输出可能看起来更随机,因此数学定位的可能性较小(因为某些结果将被过滤,输出,例如使用a where active=1):

select primary_key from table where primary_key > (34-5) 
    order by primary_key where active=1 limit 11;

30
-=34=-
80
83
100
113
125
126
127
128
129
Run Code Online (Sandbox Code Playgroud)

请注意,由于条件中的示例(例如,因为有很多非活动项)导致主键中的间隙,我不再得到最接近的5以上和5以下,而是我得到最接近的1相反,最接近9.

wup*_*tah 23

如果使用编程语言运行两个查询,有很多方法可以做到这一点,但这是在一个SQL查询中执行此操作的一种方法:

(SELECT * FROM table WHERE id >= 34 AND active = 1 ORDER BY id ASC LIMIT 6)
UNION
(SELECT * FROM table WHERE id < 34 AND active = 1 ORDER BY id DESC LIMIT 5)
ORDER BY id ASC
Run Code Online (Sandbox Code Playgroud)

这将返回上面的5行,目标行和下面的5行.


Sco*_*ley 7

这是使用分析函数超前和滞后来实现它的另一种方法.如果我们可以在WHERE子句中使用分析函数,那将是很好的.所以你需要使用子查询或CTE.这是一个适用于pagila示例数据库的示例.

WITH base AS (
    SELECT lag(customer_id, 5) OVER (ORDER BY customer_id) lag, 
      lead(customer_id, 5) OVER (ORDER BY customer_id) lead, 
      c.*
    FROM customer c
    WHERE c.active = 1
    AND c.last_name LIKE 'B%'
) 
SELECT base.* FROM base 
JOIN (
  -- Select the center row, coalesce so it still works if there aren't 
  -- 5 rows in front or behind
  SELECT COALESCE(lag, 0) AS lag, COALESCE(lead, 99999) AS lead 
  FROM base WHERE customer_id = 280
) sub ON base.customer_id BETWEEN sub.lag AND sub.lead
Run Code Online (Sandbox Code Playgroud)

sgriffinusa的解决方案的问题是你不知道你的中心行最终会是哪个row_number.他认为这将是第30行.