Toplam sonuç sayısını da (sayfalandırmadan önce) almak istiyorsanız SQL Server 2000, 2005, 2008, 2012'de sonuçları sayfalandırmanın en iyi yolu (performans açısından akıllıca) nedir?
Toplam sonuç sayısını da (sayfalandırmadan önce) almak istiyorsanız SQL Server 2000, 2005, 2008, 2012'de sonuçları sayfalandırmanın en iyi yolu (performans açısından akıllıca) nedir?
Yanıtlar:
Toplam sonuç sayısını elde etmek ve sayfalara ayırmak iki farklı işlemdir. Bu örnek uğruna, ele aldığınız sorgunun
SELECT * FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate
Bu durumda, toplam sonuç sayısını kullanarak şunları belirlersiniz:
SELECT COUNT(*) FROM Orders WHERE OrderDate >= '1980-01-01'
... verimsiz görünebilir, ancak aslında tüm dizinlerin vb.
Daha sonra, gerçek sonuçları tekrar disk belleği biçiminde almak için aşağıdaki sorgu en verimli olacaktır:
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
Bu, orijinal sorgunun 1-19. Satırlarını döndürür. Buradaki harika şey, özellikle web uygulamaları için, döndürülecek satır numaraları dışında herhangi bir durumu korumanız gerekmemesidir.
Son olarak, Microsoft SQL Server 2012 piyasaya sürüldü, bir sayfalama için basitliğini gerçekten seviyorum, burada cevaplanan gibi karmaşık sorgular kullanmak zorunda değilsiniz.
Sonraki 10 satırı almak için şu sorguyu çalıştırın:
SELECT * FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
Kullanırken dikkat edilmesi gereken önemli noktalar:
ORDER BY
OFFSET ... FETCH
fıkra kullanmak zorunludur .OFFSET
cümlesi ile zorunludur FETCH
. Kullanamazsın ORDER BY ...
FETCH
.TOP
ile kombine edilebilir değildir OFFSET
ve FETCH
aynı sorgu ifadesinde.LISTAGG()
/ ' GROUP_CONCAT()
.
FOR XML
: stackoverflow.com/a/273330/429949
FOR XML PATH ('')
. İlk olarak, XML kontrol karakterlerini XML varlık kodlarıyla değiştirir. Eğer yoksa Umut <
, >
ya &
da verilerde! İkincisi, FOR XML PATH ('')
bu şekilde kullanılan aslında belgesiz sözdizimidir. Adlandırılmış bir sütun veya alternatif bir öğe adı belirtmeniz gerekiyor. Her ikisini de yapmak dokümanda değildir, yani davranış güvenilir değildir. Üçüncüsü, kırık FOR XML PATH ('')
sözdizimini ne kadar çok kabul edersek , MS'in aslında ihtiyaç duydukları gibi gerçek bir LISTAGG() [ OVER() ]
işlev sağlaması o kadar az olasıdır .
İnanılmaz bir şekilde, başka hiçbir yanıt tüm SQL Server sürümlerinde sayfalandırma yapmanın en hızlı yolundan bahsetmemiştir . Ofsetler, burada kıyaslandığı gibi büyük sayfa numaraları için çok yavaş olabilir . SQL'de sayfalandırma yapmanın tamamen farklı, çok daha hızlı bir yolu vardır. Buna genellikle bu blog yazısında açıklandığı gibi "arama yöntemi" veya "tuş takımı sayfalaması" denir .
SELECT TOP 10 first_name, last_name, score, COUNT(*) OVER()
FROM players
WHERE (score < @previousScore)
OR (score = @previousScore AND player_id < @previousPlayerId)
ORDER BY score DESC, player_id DESC
@previousScore
Ve @previousPlayerId
değerler önceki sayfadan son kaydın ilgili değerlerdir. Bu, "sonraki" sayfayı getirmenizi sağlar. Eğer ORDER BY
yön ise ASC
, sadece kullanım >
yerine.
Yukarıdaki yöntemle, önceki 40 kaydı ilk getirmeden hemen sayfa 4'e atlayamazsınız. Ama çoğu zaman, o kadar ileri atlamak istemezsiniz. Bunun yerine, dizine ekleme işleminize bağlı olarak verileri sabit sürede alabilecek çok daha hızlı bir sorgu alırsınız. Ayrıca, temel verilerin değişmesi fark etmeksizin sayfalarınız "sabit" kalır (örneğin, sayfa 4'teyken sayfa 1'de).
Örneğin, web uygulamalarına daha fazla veri tembel olarak yüklendiğinde sayfalandırmanın en iyi yolu budur.
Not, "arama yöntemi" tuş takımı sayfalama olarak da adlandırılır .
COUNT(*) OVER()
Pencere fonksiyonu "pagination önce" toplam kayıt sayısını saymak yardımcı olacaktır. SQL Server 2000 kullanıyorsanız, için iki sorgu başvurmanız gerekir COUNT(*)
.
OFFSET .. FETCH
veya önceki ROW_NUMBER()
hilelerle ofset sayfalama uygulasanız da, tuş takımı sayfalama her zaman ofset sayfalamasını geçecektir .
RowNumber
Bana sayfa başına tutarlı 10 öğe verir. [3] pagenumber
ve varsayılan var olan ızgaralarla çalışmaz pagesize
.
SQL Server 2012'den, sayfalamayı elde etmek için OFFSET
ve FETCH NEXT
Clause kullanabiliriz .
SQL Server için şunu deneyin:
SQL Server 2012'de, ORDER BY deyiminde, ayarlanan verilerin optimizasyonunu sorgulamak ve SQL Server'daki tüm Yürütme Planı için T-SQL'de yazan herkes için veri sayfalamasıyla çalışmayı kolaylaştırmak için yeni bir özellik eklendi.
Önceki örnekte kullanılanla aynı mantığa sahip T-SQL komut dosyasının altında.
--CREATING A PAGING WITH OFFSET and FETCH clauses IN "SQL SERVER 2012" DECLARE @PageNumber AS INT, @RowspPage AS INT SET @PageNumber = 2 SET @RowspPage = 10 SELECT ID_EXAMPLE, NM_EXAMPLE, DT_CREATE FROM TB_EXAMPLE ORDER BY ID_EXAMPLE OFFSET ((@PageNumber - 1) * @RowspPage) ROWS FETCH NEXT @RowspPage ROWS ONLY;
MSDN: ROW_NUMBER (Transact-SQL)
Her bölümdeki ilk satır için 1'den başlayarak, sonuç kümesinin bir bölümündeki bir satırın sıralı sayısını döndürür.
Aşağıdaki örnek, SiparişTarihi sırasına göre 50 ila 60 arası sayılar içeren satırları döndürür.
WITH OrderedOrders AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY FirstName DESC) AS RowNumber,
FirstName, LastName, ROUND(SalesYTD,2,1) AS "Sales YTD"
FROM [dbo].[vSalesPerson]
)
SELECT RowNumber,
FirstName, LastName, Sales YTD
FROM OrderedOrders
WHERE RowNumber > 50 AND RowNumber < 60;
RowNumber FirstName LastName SalesYTD
--- ----------- ---------------------- -----------------
1 Linda Mitchell 4251368.54
2 Jae Pak 4116871.22
3 Michael Blythe 3763178.17
4 Jillian Carson 3189418.36
5 Ranjit Varkey Chudukatil 3121616.32
6 José Saraiva 2604540.71
7 Shu Ito 2458535.61
8 Tsvi Reiter 2315185.61
9 Rachel Valdez 1827066.71
10 Tete Mensa-Annan 1576562.19
11 David Campbell 1573012.93
12 Garrett Vargas 1453719.46
13 Lynn Tsoflias 1421810.92
14 Pamela Ansman-Wolfe 1352577.13
Http://www.codeproject.com/KB/aspnet/PagingLarge.aspx adresinde farklı sayfalama tekniklerine iyi bir genel bakış vardır.
ROWCOUNT yöntemini çoğunlukla SQL Server 2000 ile kullandım (2005 ve 2008 ile de çalışacak, sadece ROW_NUMBER ile karşılaştırıldığında performansı ölçecek), yıldırım hızında, ancak sıralanan sütunların (çoğunlukla) ) benzersiz değerler.
SQL Server 2000 için bir IDENTITY sütunu olan bir tablo değişkeni kullanarak ROW_NUMBER () benzetimini yapabilirsiniz:
DECLARE @pageNo int -- 1 based
DECLARE @pageSize int
SET @pageNo = 51
SET @pageSize = 20
DECLARE @firstRecord int
DECLARE @lastRecord int
SET @firstRecord = (@pageNo - 1) * @pageSize + 1 -- 1001
SET @lastRecord = @firstRecord + @pageSize - 1 -- 1020
DECLARE @orderedKeys TABLE (
rownum int IDENTITY NOT NULL PRIMARY KEY CLUSTERED,
TableKey int NOT NULL
)
SET ROWCOUNT @lastRecord
INSERT INTO @orderedKeys (TableKey) SELECT ID FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate
SET ROWCOUNT 0
SELECT t.*
FROM Orders t
INNER JOIN @orderedKeys o ON o.TableKey = t.ID
WHERE o.rownum >= @firstRecord
ORDER BY o.rownum
Bu yaklaşım, çok sütunlu tuşlara sahip tablolara genişletilebilir ve OR (performans kullanımını atlar) kullanmanın performans yükünü etkilemez. Dezavantajı, veri kümesi çok büyük ve biri son sayfanın yakınındaysa kullanılan geçici alan miktarıdır. Bu durumda imleç performansını test etmedim, ancak daha iyi olabilir.
Bu yaklaşımın verilerin ilk sayfası için optimize edilebileceğini unutmayın. Ayrıca TOP SQL Server 2000'de bir değişkeni kabul etmediğinden ROWCOUNT kullanıldı.
Sql server 2012 sayfalama için en iyi yolu bir saklı yordamda ofset ve getir sonraki kullanmaktır. OFSET Anahtar Kelime - offset yan tümcesiyle birlikte ofset kullanırsak, sorgu OFFSET n Satırda belirttiğimiz kayıt sayısını atlayacaktır.
FETCH NEXT Anahtar Kelimeler - Sonraki Getirme yan tümcesiyle bir siparişi kullandığımızda, sayfalamada görüntülemek istediğiniz satırların sayısını döndürür, Ofset olmadan SQL bir hata oluşturur. Aşağıda verilen örnek.
create procedure sp_paging
(
@pageno as int,
@records as int
)
as
begin
declare @offsetcount as int
set @offsetcount=(@pageno-1)*@records
select id,bs,variable from salary order by id offset @offsetcount rows fetch Next @records rows only
end
aşağıdaki gibi çalıştırabilirsiniz.
exec sp_paging 2,3
Bunlar SQL Server tarafında sorgu sonucu disk belleği için benim çözümler. bu yaklaşımlar SQL Server 2008 ve 2012 arasında farklıdır. Ayrıca, filtreleme ve sipariş kavramını tek bir sütunla ekledim. Gridview'da disk belleği ve filtreleme ve sipariş verirken çok etkilidir.
Test etmeden önce, bir örnek tablo oluşturmanız ve bu tabloya bir satır eklemeniz gerekir: (Gerçek dünyada tablo alanlarınızı göz önünde bulundurarak Where yan tümcesini değiştirmeniz gerekir ve belki de seçimin ana bölümünde birleştirme ve alt sorguya sahip olursunuz)
Create Table VLT
(
ID int IDentity(1,1),
Name nvarchar(50),
Tel Varchar(20)
)
GO
Insert INTO VLT
VALUES
('NAME' + Convert(varchar(10),@@identity),'FAMIL' + Convert(varchar(10),@@identity))
GO 500000
Tüm bu örnekte, sayfa başına 200 satır sorgulamak istiyorum ve 1200 numaralı sayfa için satır getiriyorum.
SQL Server 2008'de CTE konseptini kullanabilirsiniz. Bu nedenle, SQL Server 2008+ için iki tür sorgu yazdım
- SQL Server 2008+
DECLARE @PageNumber Int = 1200
DECLARE @PageSize INT = 200
DECLARE @SortByField int = 1 --The field used for sort by
DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC
DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/)
DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter
DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information.
SELECT
Data.ID,
Data.Name,
Data.Tel
FROM
(
SELECT
ROW_NUMBER()
OVER( ORDER BY
CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC'
THEN VLT.ID END ASC,
CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC'
THEN VLT.ID END DESC,
CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC'
THEN VLT.Name END ASC,
CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC'
THEN VLT.Name END ASC,
CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC'
THEN VLT.Tel END ASC,
CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC'
THEN VLT.Tel END ASC
) AS RowNum
,*
FROM VLT
WHERE
( -- We apply the filter logic here
CASE
WHEN @FilterType = 'None' THEN 1
-- Name column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 1
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.ID LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 1
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.ID NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 1
AND VLT.ID = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1
AND VLT.ID <> @FilterValue THEN 1
-- Name column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 2
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Name LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 2
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Name NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 2
AND VLT.Name = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2
AND VLT.Name <> @FilterValue THEN 1
-- Tel column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 3
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Tel LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 3
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Tel NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 3
AND VLT.Tel = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3
AND VLT.Tel <> @FilterValue THEN 1
END
) = 1
) AS Data
WHERE Data.RowNum > @PageSize * (@PageNumber - 1)
AND Data.RowNum <= @PageSize * @PageNumber
ORDER BY Data.RowNum
GO
SQL Server 2008 ve sonrasında CTE ile ikinci çözüm
DECLARE @PageNumber Int = 1200
DECLARE @PageSize INT = 200
DECLARE @SortByField int = 1 --The field used for sort by
DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC
DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/)
DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter
DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information.
;WITH
Data_CTE
AS
(
SELECT
ROW_NUMBER()
OVER( ORDER BY
CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC'
THEN VLT.ID END ASC,
CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC'
THEN VLT.ID END DESC,
CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC'
THEN VLT.Name END ASC,
CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC'
THEN VLT.Name END ASC,
CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC'
THEN VLT.Tel END ASC,
CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC'
THEN VLT.Tel END ASC
) AS RowNum
,*
FROM VLT
WHERE
( -- We apply the filter logic here
CASE
WHEN @FilterType = 'None' THEN 1
-- Name column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 1
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.ID LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 1
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.ID NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 1
AND VLT.ID = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1
AND VLT.ID <> @FilterValue THEN 1
-- Name column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 2
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Name LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 2
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Name NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 2
AND VLT.Name = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2
AND VLT.Name <> @FilterValue THEN 1
-- Tel column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 3
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Tel LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 3
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Tel NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 3
AND VLT.Tel = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3
AND VLT.Tel <> @FilterValue THEN 1
END
) = 1
)
SELECT
Data.ID,
Data.Name,
Data.Tel
FROM Data_CTE AS Data
WHERE Data.RowNum > @PageSize * (@PageNumber - 1)
AND Data.RowNum <= @PageSize * @PageNumber
ORDER BY Data.RowNum
- SQL Server 2012+
DECLARE @PageNumber Int = 1200
DECLARE @PageSize INT = 200
DECLARE @SortByField int = 1 --The field used for sort by
DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC
DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/)
DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter
DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information.
;WITH
Data_CTE
AS
(
SELECT
*
FROM VLT
WHERE
( -- We apply the filter logic here
CASE
WHEN @FilterType = 'None' THEN 1
-- Name column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 1
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.ID LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 1
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.ID NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 1
AND VLT.ID = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1
AND VLT.ID <> @FilterValue THEN 1
-- Name column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 2
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Name LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 2
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Name NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 2
AND VLT.Name = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2
AND VLT.Name <> @FilterValue THEN 1
-- Tel column filter
WHEN @FilterType = 'Contain' AND @FilterColumn = 3
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Tel LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'NotContain' AND @FilterColumn = 3
AND ( -- In this case, when the filter value is empty, we want to show everything.
VLT.Tel NOT LIKE '%' + @FilterValue + '%'
OR
@FilterValue = ''
) THEN 1
WHEN @FilterType = 'Match' AND @FilterColumn = 3
AND VLT.Tel = @FilterValue THEN 1
WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3
AND VLT.Tel <> @FilterValue THEN 1
END
) = 1
)
SELECT
Data.ID,
Data.Name,
Data.Tel
FROM Data_CTE AS Data
ORDER BY
CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC'
THEN Data.ID END ASC,
CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC'
THEN Data.ID END DESC,
CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC'
THEN Data.Name END ASC,
CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC'
THEN Data.Name END ASC,
CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC'
THEN Data.Tel END ASC,
CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC'
THEN Data.Tel END ASC
OFFSET @PageSize * (@PageNumber - 1) ROWS FETCH NEXT @PageSize ROWS ONLY;
Akıllıca kullanın, aşağıdakilerin kullanımı kolay ve hızlı görünmektedir. Sadece sayfa numarasını ayarlamanız yeterli.
use AdventureWorks
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 6;
with result as(
SELECT SalesOrderDetailID, SalesOrderID, ProductID,
ROW_NUMBER() OVER (ORDER BY SalesOrderDetailID) AS RowNum
FROM Sales.SalesOrderDetail
where 1=1
)
select SalesOrderDetailID, SalesOrderID, ProductID from result
WHERE result.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1
AND @RowsPerPage*(@PageNumber)
CTE olmadan da
use AdventureWorks
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 6
SELECT SalesOrderDetailID, SalesOrderID, ProductID
FROM (
SELECT SalesOrderDetailID, SalesOrderID, ProductID,
ROW_NUMBER() OVER (ORDER BY SalesOrderDetailID) AS RowNum
FROM Sales.SalesOrderDetail
where 1=1
) AS SOD
WHERE SOD.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1
AND @RowsPerPage*(@PageNumber)
Peki SQL 2000 veritabanımda aşağıdaki örnek sorgu kullandık, SQL 2005 için de iyi çalışıyor. Verdiği güç, birden çok sütun kullanarak dinamik olarak sıralanır. Sana söylüyorum ... bu güçlü :)
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
En iyi bölüm sp_executesql, aynı parametreleri iletmeniz koşuluyla daha sonraki çağrıları önbelleğe alır.
CREATE view vw_sppb_part_listsource as
select row_number() over (partition by sppb_part.init_id order by sppb_part.sppb_part_id asc ) as idx, * from (
select
part.SPPB_PART_ID
, 0 as is_rev
, part.part_number
, part.init_id
from t_sppb_init_part part
left join t_sppb_init_partrev prev on ( part.SPPB_PART_ID = prev.SPPB_PART_ID )
where prev.SPPB_PART_ID is null
union
select
part.SPPB_PART_ID
, 1 as is_rev
, prev.part_number
, part.init_id
from t_sppb_init_part part
inner join t_sppb_init_partrev prev on ( part.SPPB_PART_ID = prev.SPPB_PART_ID )
) sppb_part
farklı init_id söz konusu olduğunda idx'i yeniden başlatacak
Teknik için, ROW_NUMBER
kullanılacak bir sıralama sütununuz yoksa, CURRENT_TIMESTAMP
aşağıdaki gibi kullanabilirsiniz :
SELECT TOP 20
col1,
col2,
col3,
col4
FROM (
SELECT
tbl.col1 AS col1
,tbl.col2 AS col2
,tbl.col3 AS col3
,tbl.col4 AS col4
,ROW_NUMBER() OVER (
ORDER BY CURRENT_TIMESTAMP
) AS sort_row
FROM dbo.MyTable tbl
) AS query
WHERE query.sort_row > 10
ORDER BY query.sort_row
Bu, 700.000'e kadar masa boyutlarında arama yapmak için benim için iyi çalıştı.
Bu, 11 ila 30 arasındaki kayıtları getirir.
create PROCEDURE SP_Company_List (@pagesize int = -1 ,@pageindex int= 0 ) > AS BEGIN SET NOCOUNT ON; select Id , NameEn from Company ORDER by Id ASC OFFSET (@pageindex-1 )* @pagesize ROWS FETCH NEXt @pagesize ROWS ONLY END GO
DECLARE @return_value int EXEC @return_value = [dbo].[SP_Company_List] @pagesize = 1 , > @pageindex = 2 SELECT 'Return Value' = @return_value GO
Bu bit, SQL Server'ı ve daha yeni MySQL sürümlerini kullanarak sayfalama yapabilmenizi sağlar ve her satırdaki toplam satır sayısını taşır. Benzersiz satır sayısını saymak için pimary anahtarınızı kullanır.
WITH T AS
(
SELECT TABLE_ID, ROW_NUMBER() OVER (ORDER BY TABLE_ID) AS RN
, (SELECT COUNT(TABLE_ID) FROM TABLE) AS TOTAL
FROM TABLE (NOLOCK)
)
SELECT T2.FIELD1, T2.FIELD2, T2.FIELD3, T.TOTAL
FROM TABLE T2 (NOLOCK)
INNER JOIN T ON T2.TABLE_ID=T.TABLE_ID
WHERE T.RN >= 100
AND T.RN < 200
Bu 2012 eski SO sorununun bir kopyasıdır: sayfalamayı uygulamanın etkili yolu
[TableX] SİPARİŞ TARAFINDAN [FieldX] OFSET 500 ROWS FETCH NEXT SADECE 100 ROWS
Burada konu daha ayrıntılı olarak ve alternatif yaklaşımlarla tartışılmaktadır.
Dili veya hangi sürücüyü kullandığınızı belirtmediniz. Bu yüzden soyut olarak tarif ediyorum.