Проблема с отслеживанием SQL-запросов - PullRequest
2 голосов
/ 11 мая 2011

Хорошо, вот мой вопрос.

Пользователь может зайти на мой сайт и одновременно получить 8 записей, после чего ему / ей предоставляется возможность загружать больше. Эти 8 записей могут быть отсортированы по параметру, переданному в proc. Теперь, когда я получаю эти 8 записей во внешнем интерфейсе, у меня есть их идентификаторы (скрытые для пользователя, хотя, очевидно), но их идентификаторы не в каком-либо определенном порядке, потому что записи сортируются различными способами.

Когда они нажмут «Загрузить еще», я смогу получить следующие 8 записей из базы данных, отсортированные таким же образом, как и первые 8.

Например, «Дайте мне 8 лучших записей, отсортированных по возрасту». -> Нажмите Загрузить еще -> Дайте мне следующие 8 самых старых записей, не показывая мне только что увиденные вещи.

Как я могу вызвать proc и убедиться, что ничего из первого набора результатов не возвращено? Я хочу вернуть только 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

Это мой текущий запрос. Как бы я изменил его для работы с подкачкой?

Ответы [ 2 ]

3 голосов
/ 11 мая 2011

использовать row_number

пример

вызов 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

edit, вот как это должно выглядеть, вы, вероятно, также хотите вернуть максимальное количество строк, чтобы вы знали, сколько строк может быть потенциально возвращено также вы можете сделать строки на странице динамическими, в этом случае это будет что-то вроде

где строки между @StartRow и (@StartRow + @RowsPerPage) -1

обязательно прочитайте Условия динамического поиска в версии T-SQL для SQL 2008 , чтобы увидеть, как можно оптимизировать это, чтобы получить повторное использование плана и лучший план в целом

В любом случае, вот процедура, конечно, не проверенная, поскольку я не могу запустить ее здесь

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 голосов
/ 11 мая 2011

У Дэвида Хейдена есть хорошая статья о подкачке страниц.Вам просто нужно следить за количеством записей и смещением.

Также вам все равно придется объединять и обрабатывать записи на клиенте каждый раз, когда они загружают больше

Вот 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 
...