Вот полный подход @tjunglc с циклом:
protected function getPrevNext($aArray,$key)
{
$aKeys = array_keys($aArray); //every element of aKeys is obviously unique
$aIndices = array_flip($aKeys); //so array can be flipped without risk
$i = $aIndices[$key]; //index of key in aKeys
if ($i > 0) $prev = $aArray[$aKeys[$i-1]]; //use previous key in aArray
if ($i < count($aKeys)-1) $next = $aArray[$aKeys[$i+1]]; //use next key in aArray
if (!isset($prev)) $prev = end($aArray);
if (!isset($next)) $next = reset($aArray);
return array($prev,$next);
}
Oh и thankx @tjunglc для этого:)
Получение общего количества результатов и разбиения на страницы является двумя различными операциями. Ради этого примера давайте предположим, что запрос, с которым Вы имеете дело,
SELECT * FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate
В этом случае, Вы определили бы общее количество использования результатов:
SELECT COUNT(*) FROM Orders WHERE OrderDate >= '1980-01-01'
..., который может казаться неэффективным, но на самом деле довольно производителен, принимая все индексы и т.д., правильно настраиваются.
затем для возвращения фактических результатов разбитым на страницы способом следующий запрос был бы самым эффективным:
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, *
FROM Orders
WHERE OrderDate >= '1980-01-01'
) AS RowConstrainedResult
WHERE RowNum >= 1
AND RowNum < 20
ORDER BY RowNum
Это возвратит строки 1-19 из исходного запроса. Прохладная вещь здесь, специально для веб-приложений, состоит в том, что Вы не должны сохранять состояние, кроме номеров строк, которые будут возвращены.
Вы не определили язык, ни какой драйвер Вы используете. Поэтому я описываю его абстрактно.
Существует хороший обзор различных разбиений памяти на страницы в http://www.codeproject.com/KB/aspnet/PagingLarge.aspx
, я использовал метод ROWCOUNT довольно часто главным образом с SQL Server 2000 (будет работать с 2 005 & 2008 также, просто измерьте уровень по сравнению с ROW_NUMBER), это - молния быстро, но необходимо удостовериться, что отсортированный столбец (столбцы) имеет (главным образом) уникальные значения.
Что ж, я использовал следующий пример запроса в своей базе данных SQL 2000, он хорошо работает и для SQL 2005. Он дает вам возможность динамического упорядочивания с использованием нескольких столбцов. Я говорю вам ... это мощно :)
ALTER PROCEDURE [dbo].[RE_ListingReports_SelectSummary]
@CompanyID int,
@pageNumber int,
@pageSize int,
@sort varchar(200)
AS
DECLARE @sql nvarchar(4000)
DECLARE @strPageSize nvarchar(20)
DECLARE @strSkippedRows nvarchar(20)
DECLARE @strFields nvarchar(4000)
DECLARE @strFilter nvarchar(4000)
DECLARE @sortBy nvarchar(4000)
DECLARE @strFrom nvarchar(4000)
DECLARE @strID nvarchar(100)
If(@pageNumber < 0)
SET @pageNumber = 1
SET @strPageSize = CAST(@pageSize AS varchar(20))
SET @strSkippedRows = CAST(((@pageNumber - 1) * @pageSize) AS varchar(20))-- For example if pageNumber is 5 pageSize is 10, then SkippedRows = 40.
SET @strID = 'ListingDbID'
SET @strFields = 'ListingDbID,
ListingID,
[ExtraRoom]
'
SET @strFrom = ' vwListingSummary '
SET @strFilter = ' WHERE
CompanyID = ' + CAST(@CompanyID As varchar(20))
End
SET @sortBy = ''
if(len(ltrim(rtrim(@sort))) > 0)
SET @sortBy = ' Order By ' + @sort
-- Total Rows Count
SET @sql = 'SELECT Count(' + @strID + ') FROM ' + @strFROM + @strFilter
EXEC sp_executesql @sql
--// This technique is used in a Single Table pagination
SET @sql = 'SELECT ' + @strFields + ' FROM ' + @strFROM +
' WHERE ' + @strID + ' IN ' +
' (SELECT TOP ' + @strPageSize + ' ' + @strID + ' FROM ' + @strFROM + @strFilter +
' AND ' + @strID + ' NOT IN ' + '
(SELECT TOP ' + @strSkippedRows + ' ' + @strID + ' FROM ' + @strFROM + @strFilter + @SortBy + ') '
+ @SortBy + ') ' + @SortBy
Print @sql
EXEC sp_executesql @sql
Самое приятное то, что sp_executesql кэширует последующие вызовы при условии, что вы передаете те же параметры, то есть генерируете тот же текст sql.