存储SQL Server查询分页的结果

时间:2013-11-21 03:14:16

标签: sql sql-server database pagination

在我的数据库中,我有一个包含相当大数据集的表,用户可以对其进行搜索。因此,对于包含大约250,000条记录的Person表的以下表结构:

firstName|lastName|age
---------|--------|---
John     | Doe    |25
---------|--------|---
John     | Sams   |15
---------|--------|---

用户将能够执行可以返回大约500个左右的结果的查询。我想做的是允许用户使用分页一次查看他的搜索结果50。我已经找到了客户端分页的东西,但是我需要在某处存储查询结果,以便分页使用来自其唯一查询的结果,而不是来自SELECT *语句。

任何人都可以就实现这一目标的最佳方式提供一些指导吗?谢谢。

旁注:我一直在尝试使用临时表来使用SELECT INTO语句来执行此操作,但我认为如果用户A执行搜索并且存储结果,则可能会导致一些问题在临时表中,用户B不久后执行搜索,并覆盖用户A的搜索结果。

3 个答案:

答案 0 :(得分:2)

在SQL Server中,ROW_NUMBER()函数非常适合分页,并且可能会有所帮助,具体取决于搜索之间的参数变化,例如,如果搜索只是针对您可以使用的不同firstName值:

;WITH search AS (SELECT *,ROW_NUMBER() OVER (PARTITION BY firstName ORDER BY lastName) AS RN_firstName
                 FROM YourTable)
SELECT *
FROM search 
WHERE RN BETWEEN 51 AND 100
  AND firstName = 'John'

您可以添加其他ROW_NUMBER()行,根据搜索的字段更改PARTITION BY子句。

答案 1 :(得分:1)

首先,确保你真的需要这样做。你增加了很大的复杂性,所以去&衡量查询和分页是否真的很痛,或者你只是“觉得你应该”。可以很容易地使用ROW_NUMBER()处理分页。

假设你继续,一旦你得到了你的查询,显然你需要建立一个缓存,所以首先你需要确定密钥是什么。它将是SQL语句或操作标识符(可能是存储过程的名称)和使用的标准。如果您不想在用户之间共享用户名或某种会话ID。

现在,当您进行查询时,首先要在此表中查找所有关键数据,然后

a)无法找到它,因此您运行查询并添加到缓存,存储条件/键和数据的数据或PK,具体取决于您是想要快照还是实时。请记住,“实时”并非真正因为其他用户可能正在改变您的数据。

b)找到它,所以删除结果(或将PK加入基础表)并返回结果。

当然,现在你需要一个后台进程来清理缓存,因为缓存太长了。

就像我说的那样 - 在开始之前,你应该确保你需要这样做。在你给出的例子中,我认为这不值得。

答案 2 :(得分:0)

从历史上看,对我们来说,管理它的最佳方法是创建一个具有唯一名称的完整新表。然后,当您完成后,您可以安排表格进行删除。

如果可行,该表只包含一个索引id(一个简单的序列:1,2,3,4,5)和作为查询一部分的表的主键。不是整个结果集。

您的分页逻辑会执行以下操作:

SELECT p.* FROM temp_1234 t, primary_table p 
WHERE t.pkey = p.primary_key 
  AND t.serial_id between 51 and 100

序列号是您的分页索引。

所以,你最终得到的东西(注意,我不是SQL Server的人,所以请原谅):

CREATE TABLE temp_1234 (
    serial_id serial,
    pkey number
);

INSERT INTO temp_1234
  SELECT 0, primary_key FROM primary_table WHERE <criteria> ORDER BY <sort>;

CREATE INDEX i_temp_1234 ON temp_1234(serial_id); // I think sql already does this for you

如果你可以延迟索引,它比首先创建它更快,但最有可能是一个微小的改进。

此外,创建一个跟踪表,您可以在其中插入表名和日期。您可以在晚些时候(深夜)使用收割机进程来DROP日期表(比那些X小时更多)。

全表操作比在单个表中插入和删除行要便宜得多:

INSERT INTO page_table SELECT 'temp_1234', <sequence>, primary_key...

DELETE FROM page_table WHERE page_id = 'temp_1234';

那太糟糕了。