从数据库中获取消息1-20,21-40,....

时间:2010-02-04 16:28:30

标签: sql sql-server oracle sybase

我正在尝试构建一个邮箱,我们可以将邮件分组为x。 如果您将x设置为20,您将在第一页上看到消息1-20,打开第二页将显示消息21-40等。

如何有效地查询?我能想到的最好的是:

select top 20 * 
from tbl_messages
where 
tnr_id not in
(
    select top 40 tnr_id   —20/40/60/80/…
    from tbl_messages
    order by dt_made desc, tnr_id desc
)
order by dt_made desc, tnr_id desc

有更有效的方法吗?使用的数据库是SQL server,oracle& SYBASE。

3 个答案:

答案 0 :(得分:4)

Oracle

SELECT  *
FROM    (
        SELECT  t.*, rownum AS rn
        FROM    tbl_messages t
        ORDER BY
                dt_made DESC, tnr_id DESC
        )
WHERE   rn > 40
        AND rownum <= 20

SQL Server 2005及以上:

DECLARE @start INT
DECLARE @pagesize INT
SET @start = 40
SET @pagesize = 20  

SELECT  *
FROM    (
        SELECT  TOP (@start + @pagesize)
                t.*, ROW_NUMBER() OVER (ORDER BY dt_made DESC, tnr_id DESC) AS rn
        FROM    tbl_messages t
        ORDER BY
                dt_made DESC, tnr_id DESC
        ) q
WHERE   rn > @start
ROW_NUMBER也支持

Oracle,但由于实施细节效率低于rownum

在我的博客中查看此文章以进行性能比较:

<强>更新

如果您可以容忍并发更新导致的一些差异,您可以记住客户端当前页面上的最后一条记录,并使用它来更快地获得下一个结果:

SELECT  TOP 20 *
FROM    tbl_messages t
WHERE   dt_made <= @last_dt_made
        AND NOT (dt_made = @last_dt_made AND tnr_id >= @last_tnr_id)
ORDER BY
        dt_made DESC, tnr_id DESC

答案 1 :(得分:0)

对于SQL Server,试试这个:

--set up a table to page through:
DECLARE @TestTable  table (TableID int )

INSERT INTO @TestTable (TableID)
SELECT TOP 1000 row_number() over(order by t1.number) as N
FROM master..spt_values t1 
    CROSS JOIN master..spt_values t2

--set page location and size
DECLARE @Start  int
DECLARE @Size   int

SET @Start=40
SET @Size=20

--return data for that page:
SELECT
    *
    FROM (SELECT 
              v.*, ROW_NUMBER() OVER (ORDER BY TableID) AS RowNumber
              FROM  @TestTable  v
         ) dt
    WHERE RowNumber>=@Start AND RowNumber<@Start+@Size

输出:

TableID     RowNumber
----------- --------------------
40          40
41          41
42          42
43          43
44          44
45          45
46          46
47          47
48          48
49          49
50          50
51          51
52          52
53          53
54          54
55          55
56          56
57          57
58          58
59          59

(20 row(s) affected)

答案 2 :(得分:0)

对于SQL Server - 可能更灵活,允许您指定页码和每页消息

DECLARE @pageNumber int, @messagesPerPage int
SET @pageNumber = 3
SET @messagesPerPage = 20

SELECT *
  FROM (
        SELECT t.*, ROW_NUMBER() OVER (ORDER BY [dt_made] DESC, [tnr_id] DESC) AS __RN
          FROM tbl_messages t
       ) iDat
 WHERE __RN BETWEEN (@pageNumber - 1) * @messagesPerPage AND @pageNumber * @messagesPerPage
 ORDER BY dt_made DESC, tnr_id DESC