SQL 查询跟踪问题

问题描述 投票:0回答:2

好的,这就是我的问题。

用户可以访问我的网站并一次检索 8 条记录,然后他/她可以选择加载更多记录。这 8 条记录可以通过传递到过程中的参数进行排序。现在,当我在前端获取这 8 条记录时,我有它们的 ID(虽然显然对用户来说是隐藏的),但它们的 ID 没有任何特定的顺序,因为记录是按各种可能的事物排序的。

当他们单击“加载更多”时,我应该能够从数据库中获取接下来的 8 条记录,其排序方式与前 8 条记录相同。

例如,“给我按年龄排序的前 8 条记录”。 -> 单击“加载更多”-> 给我接下来 8 个最旧的记录,而不显示我刚刚看到的一次。

如何调用该过程并确保第一个结果集中没有返回?出于效率原因,我只想一次返回 8 条记录。

SELECT TOP 8
      m.message,
      m.votes,
      (geography::Point(@latitude, @longitude, 4326).STDistance(m.point)) * 0.000621371192237334 as distance,
      m.location,
      datediff(hour,m.timestamp, getdate()) as age,
      m.messageId,
      ml.voted,
      ml.flagged
    FROM
      tblMessages m
    left join tblIPMessageLink ml on m.messageid = ml.messageid
    WHERE
      m.timestamp >= DATEADD(day, DATEDIFF(day, 0, @date), 0)
      and
      m.timestamp < DATEADD(day, DATEDIFF(day, 0, @date), 1)
      ORDER BY
        CASE WHEN @sort = 'votes1' THEN m.votes END DESC,
        CASE WHEN @sort = 'votes2' THEN m.votes END ASC,
        CASE WHEN @sort = 'age1' THEN datediff(hour,m.timestamp, getdate()) END ASC,
        CASE WHEN @sort = 'age2' THEN datediff(hour,m.timestamp, getdate()) END DESC,
        CASE WHEN @sort = 'distance1' THEN (geography::Point(@latitude, @longitude, 4326).STDistance(m.point)) * 0.000621371192237334 END ASC,
        CASE WHEN @sort = 'distance2' THEN (geography::Point(@latitude, @longitude, 4326).STDistance(m.point)) * 0.000621371192237334 END DESC
      END

这是我当前的查询。我如何更改它以与分页一起使用?

c# .net t-sql sql-server-2008 pagination
2个回答
3
投票

使用行号

示例

拨打1

;WITH cte AS(SELECT *,row_number() OVER( ORDER BY name) AS rows FROM sysobjects)

SELECT * FROM cte WHERE ROWS BETWEEN 1 AND 8
ORDER BY rows

拨打2

;WITH cte AS(SELECT *,row_number() OVER( ORDER BY name) AS rows FROM sysobjects)

SELECT * FROM cte WHERE ROWS BETWEEN 9 AND 16
ORDER BY rows

当然你想使用参数而不是硬编码数字,这样你就可以重用查询,如果列可以任意排序那么你可能需要使用动态SQL

编辑,这应该是这样的,您可能还想返回最大行数,以便知道可以返回多少行 您也可以使每页的行动态,在这种情况下,它会像

其中 @StartRow 和 (@StartRow + @RowsPerPage) -1 之间的行

请务必阅读 SQL 2008 的 T-SQL 版本中的动态搜索条件,了解如何优化它以获得计划重用和总体上更好的计划

无论如何,这是过程,当然未经测试,因为我无法在这里运行它

DECLARE @StartRow INT,@EndRow INT
--SELECT @StartRow =1, @EndRow = 8


;WITH cte AS (SELECT ROW_NUMBER() OVER (ORDER BY
        CASE WHEN @sort = 'votes1' THEN m.votes END DESC,
        CASE WHEN @sort = 'votes2' THEN m.votes END ASC,
        CASE WHEN @sort = 'age1' THEN datediff(hour,m.timestamp, getdate()) END ASC,
        CASE WHEN @sort = 'age2' THEN datediff(hour,m.timestamp, getdate()) END DESC,
        CASE WHEN @sort = 'distance1' THEN (geography::Point(@latitude, @longitude, 4326).STDistance(m.point)) * 0.000621371192237334 END ASC,
        CASE WHEN @sort = 'distance2' THEN (geography::Point(@latitude, @longitude, 4326).STDistance(m.point)) * 0.000621371192237334 END DESC
      END) AS rows 
      m.message,
      m.votes,
      (geography::Point(@latitude, @longitude, 4326).STDistance(m.point)) * 0.000621371192237334 as distance,
      m.location,
      datediff(hour,m.timestamp, getdate()) as age,
      m.messageId,
      ml.voted,
      ml.flagged
    FROM
      tblMessages m
    left join tblIPMessageLink ml on m.messageid = ml.messageid
    WHERE
      m.timestamp >= DATEADD(day, DATEDIFF(day, 0, @date), 0)
      and
      m.timestamp < DATEADD(day, DATEDIFF(day, 0, @date), 1)
      )


     SELECT * 
     FROM cte WHERE ROWS BETWEEN @StartRow AND @EndRow
    ORDER BY rows

2
投票

David Hayden 有一篇关于分页的好文章。您只需要跟踪记录数和偏移量即可。

此外,每次加载更多记录时,您仍然需要在客户端上合并和重新排序记录

这是那篇文章的 SP

CREATE PROCEDURE dbo.ShowLog
    @PageIndex INT, 
    @PageSize INT 
AS

BEGIN 

WITH LogEntries AS ( 
SELECT ROW_NUMBER() OVER (ORDER BY Date DESC)
AS Row, Date, Description 
FROM LOG)

SELECT Date, Description
FROM LogEntries 
WHERE Row between 
(@PageIndex - 1) * @PageSize + 1 and @PageIndex*@PageSize



END 
© www.soinside.com 2019 - 2024. All rights reserved.