【问题标题】:SQL - Get Next and Previous X recordsSQL - 获取下一条和上一条 X 记录
【发布时间】:2017-04-09 08:01:36
【问题描述】:

我正在尝试在 postgresql 中使用一个查询,该查询可以根据用于某些分页的起始记录 ID 获取上一个和下一个 X 条记录。只获得 1 下一个或上一个并不难,但这不是我需要的。

我发现了一些很接近的查询,但我对 PostgreSQL 查询的了解不够,无法执行这些类型的复杂查询。

下面的这个查询我尝试并更改为工作,但似乎只带回了 ID 的前一项和下一项以及 所有 记录。

但我需要能够为它提供一个起点,例如在WHERE 子句中提供一个 ID,并且如果它们存在,则只能获得 10 条上一条和 10 条下一条记录。这可以单独在 sql 中完成吗?

SELECT
  m.med_id AS id,
  coalesce(
      LEAD(m.med_id) OVER (ORDER BY m.med_id DESC),
      (select med.med_id from media as med order by med.med_id desc limit 1)
  ) AS nextitemid,
  coalesce(
      LAG(m.med_id) OVER (ORDER BY m.med_id DESC),
      (select med.med_id from media as med order by med.med_id asc limit 1)
  ) AS previtemid
FROM media m
WHERE m.post_type = 1
ORDER BY m.med_id DESC LIMIT 20;

任何帮助都将不胜感激,它可以是任何类型的 sql 解决方案来实现这一点。

我相信所需的输出来自一个示例,即 100 个项目,以 50 作为查询中提供的 ID 起点。

|previtemids|nextitemids|
    49           51
    48           52
    47           53
    46           54
    45           55
    44           56
    43           57
    42           58 
    41           59 
    40           60 

我已经接近但无法在一次查询中得到它。与我的场景接近的答案比通用答案更有帮助。

【问题讨论】:

  • 您想要列中的 10 条上一条和 10 条下一条记录,还是每条记录单独一行?
  • 嗯,好问题@Alex 我将把它从 PHP 读取到一个数组中。也许列可能更容易?
  • 您能否发布一个您想要的输出示例?
  • @alex 我提供了一个例子
  • 我收回了。它几乎可以工作,但还不够

标签: sql postgresql postgresql-9.1


【解决方案1】:
with numbered as(
   select your_table.*, row_number() over(order by id) as rn from your_table 
)
SELECT previous.id, next.id FROM 
(SELECT id, row_number() over(order by id) as inner_rn FROM numbered where rn between (select rn from numbered WHERE id = 12) - 5 and (select rn from numbered WHERE id = 12) -1) previous
INNER JOIN 
(SELECT id, row_number() over(order by id) as inner_rn FROM numbered where rn between (select rn from numbered WHERE id = 12) + 1 and (select rn from numbered WHERE id = 12) + 5) next
ON previous.inner_rn = next.inner_rn

如果我正确理解你需要这个

这里 12 是 starting point providing an ID,5 是下一条和上一条 X 条记录

(注:例如,如果没有前10行,但有10下一行,你需要用NULL填写遗漏的值,然后使用FULL JOIN而不是INNER JOIN

【讨论】:

  • 所以这并没有真正产生正确的结果。我的查询有点接近我需要的。只是没有按预期工作。
  • 那么你需要不同两列中的前一个和下一个 x id 吗? (如在您编辑的示例中?)
  • 我认为那将是理想的
  • 好的,我的查询已接近但不完全。
  • 更接近了,我有另一个表需要与示例中的主表连接。在我的问题中查看我上面的旧查询以了解我的意思。
【解决方案2】:

所以这就是如何完成的,我们使用它来生成 0-1000 之间的 100 个随机数字..

SELECT
  trunc(random()*1000) AS x
FROM generate_series(1,100);

现在我们给定一个 80 的 id,我们可以在这里找到 70-90 的范围。

SELECT *
FROM (
  SELECT rank() OVER (ORDER BY x) AS dr, x
  FROM (
    SELECT
      trunc(random()*1000) AS x
    FROM generate_series(1,100)
  ) AS t
) AS t
WHERE dr BETWEEN 80-10 AND 80+10;

 dr |  x  
----+-----
 70 | 702
 71 | 706
 72 | 718
 73 | 734
 74 | 751
 75 | 756
 76 | 774
 77 | 778
 78 | 805
 79 | 813
 80 | 829
 81 | 833
 82 | 839
 83 | 852
 84 | 853
 85 | 872
 86 | 884
 86 | 884
 88 | 892
 89 | 897
 90 | 905
(21 rows)

但我不会这样做。我会通过传递一个 id 和所需的行来进行分页。并且只允许前进。将之前的结果存储在浏览器中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    相关资源
    最近更新 更多