ما هي أفضل طريقة لترقيم الصفحات النتائج في SQL Server
-
01-07-2019 - |
سؤال
ما هي أفضل طريقة (من حيث الأداء) لترقيم الصفحات النتائج في SQL Server 2000، 2005، 2008، 2012 إذا كنت تريد أيضًا الحصول على العدد الإجمالي للنتائج (قبل ترقيم الصفحات)؟
المحلول
الحصول على العدد الإجمالي للنتائج وترقيم الصفحات هما عمليتان مختلفتان.من أجل هذا المثال، لنفترض أن الاستعلام الذي تتعامل معه هو
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 من الاستعلام الأصلي.الشيء الرائع هنا، خاصة بالنسبة لتطبيقات الويب، هو أنك لست مضطرًا إلى الاحتفاظ بأي حالة، باستثناء أرقام الصفوف التي سيتم إرجاعها.
نصائح أخرى
أخيراً، مايكروسوفت SQL خادم 2012 تم إصداره، وأنا حقًا أحب بساطته بالنسبة إلى ترقيم الصفحات، فلا يتعين عليك استخدام الاستعلامات المعقدة مثل الإجابة هنا.
للحصول على الصفوف العشرة التالية، قم فقط بتشغيل هذا الاستعلام:
SELECT * FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
http://technet.microsoft.com/en-us/library/gg699618.aspx
النقاط الرئيسية التي يجب مراعاتها عند استخدامه:
- ORDER BY إلزامي لاستخدام عبارة OFFSET وFETCH.
- شرط OFFSET إلزامي مع FETCH.لا يمكنك أبدًا استخدام ، طلب ... جلب.
- لا يمكن دمج الأعلى مع الإزاحة وجلبه في نفس التعبير عن الاستعلام.
بشكل لا يصدق، لم تذكر أي إجابة أخرى الأسرع طريقة عمل ترقيم الصفحات في كافة إصدارات SQL Server.يمكن أن تكون الإزاحات بطيئة للغاية بالنسبة لأعداد الصفحات الكبيرة كما هي قياسا هنا.هناك طريقة مختلفة تمامًا وأسرع بكثير لتنفيذ ترقيم الصفحات في SQL.يُطلق على هذا غالبًا اسم "طريقة البحث" أو "ترقيم الصفحات لمجموعة المفاتيح" كما هو موضح في هذا بلوق وظيفة هنا.
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
و @previousPlayerId
القيم هي القيم الخاصة بالسجل الأخير من الصفحة السابقة.يتيح لك ذلك جلب الصفحة "التالية".إذا ORDER BY
الاتجاه هو ASC
, ، استخدم ببساطة >
بدلاً من.
باستخدام الطريقة المذكورة أعلاه، لا يمكنك الانتقال فورًا إلى الصفحة 4 دون جلب السجلات الأربعين السابقة أولاً.لكن في كثير من الأحيان، لا ترغب في القفز إلى هذا الحد على أي حال.بدلاً من ذلك، ستحصل على استعلام أسرع بكثير قد يكون قادرًا على جلب البيانات في وقت ثابت، اعتمادًا على الفهرسة الخاصة بك.بالإضافة إلى ذلك، تظل صفحاتك "مستقرة"، بغض النظر عما إذا كانت البيانات الأساسية قد تغيرت (على سبيل المثال.في الصفحة 1، بينما أنت في الصفحة 4).
هذه هي أفضل طريقة لتنفيذ ترقيم الصفحات عند التحميل البطيء لمزيد من البيانات في تطبيقات الويب، على سبيل المثال.
لاحظ أن "طريقة البحث" تسمى أيضًا ترقيم الصفحات مجموعة المفاتيح.
إجمالي السجلات قبل ترقيم الصفحات
ال COUNT(*) OVER()
ستساعدك وظيفة النافذة على حساب إجمالي عدد السجلات "قبل ترقيم الصفحات".إذا كنت تستخدم SQL Server 2000، فسيتعين عليك اللجوء إلى استعلامين لـ COUNT(*)
.
من SQL Server 2012، يمكننا استخدام OFFSET
و FETCH NEXT
بند لتحقيق ترقيم الصفحات.
جرب هذا لـ SQL Server:
في SQL Server 2012 ، تمت إضافة ميزة جديدة بالترتيب عن طريق الجملة ، للاستعلام عن تحسين البيانات المحددة ، مما يجعل العمل أسهل مع ترحيل البيانات لأي شخص يكتب في T-SQL وكذلك لخطة التنفيذ بأكملها في SQL Server.
أسفل البرنامج النصي T-SQL مع نفس المنطق المستخدم في المثال السابق.
--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;
هناك نظرة عامة جيدة على تقنيات الترحيل المختلفة في http://www.codeproject.com/KB/aspnet/PagingLarge.aspx
لقد استخدمت طريقة ROWCOUNT في كثير من الأحيان مع SQL Server 2000 (ستعمل مع 2005 و 2008 أيضًا، ما عليك سوى قياس الأداء مقارنةً بـ ROW_NUMBER)، إنها سريعة جدًا، ولكنك تحتاج إلى التأكد من أن الأعمدة (الأعمدة) التي تم فرزها بها (في الغالب) ) القيم الفريدة.
شبكة MSDN:ROW_NUMBER (Transact-SQL)
إرجاع الرقم التسلسلي لصف داخل قسم من مجموعة النتائج، بدءًا من 1 للصف الأول في كل قسم.
يقوم المثال التالي بإرجاع صفوف تحتوي على أرقام من 50 إلى 60 ضمناً بترتيب OrderDate.
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
بالنسبة لـ SQL Server 2000، يمكنك محاكاة ROW_NUMBER() باستخدام متغير جدول بعمود IDENTITY:
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
يمكن توسيع هذا الأسلوب ليشمل الجداول التي تحتوي على مفاتيح متعددة الأعمدة، ولا يتحمل عبء الأداء الناتج عن استخدام OR (الذي يتخطى استخدام الفهرس).الجانب السلبي هو مقدار المساحة المؤقتة المستخدمة إذا كانت مجموعة البيانات كبيرة جدًا وكانت إحداها قريبة من الصفحة الأخيرة.لم أختبر أداء المؤشر في هذه الحالة، لكنه قد يكون أفضل.
لاحظ أنه يمكن تحسين هذا الأسلوب للصفحة الأولى من البيانات.كما تم استخدام ROWCOUNT نظرًا لأن TOP لا يقبل متغيرًا في SQL Server 2000.
أفضل طريقة للترحيل في SQL Server 2012 هي استخدام الإزاحة والجلب التالي في الإجراء المخزن.إزاحة الكلمة الرئيسية - إذا استخدمنا الإزاحة بالترتيب حسب الجملة، فسيتخطى الاستعلام عدد السجلات التي حددناها في OFFSET n Rows.
جلب الكلمات الرئيسية التالية - عندما نستخدم Fetch Next مع ترتيب حسب الجملة فقط، فإنه سيُرجع عدد الصفوف التي تريد عرضها في الترحيل، وبدون الإزاحة، سيُنشئ SQL خطأً.هنا هو المثال الوارد أدناه.
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
يمكنك تنفيذه على النحو التالي.
exec sp_paging 2,3
هذه هي الحلول الخاصة بي لترحيل نتيجة الاستعلام في جانب خادم SQL.تختلف هذه الأساليب بين SQL Server 2008 و2012.كما قمت بإضافة مفهوم التصفية والترتيب بعمود واحد.إنه فعال للغاية عند الترحيل والتصفية والطلب في Gridview الخاص بك.
قبل الاختبار، عليك إنشاء جدول نموذجي واحد وإدراج بعض الصفوف في هذا الجدول:(في العالم الحقيقي، يتعين عليك تغيير عبارة Where مع الأخذ في الاعتبار حقول الجدول الخاص بك وربما يكون لديك بعض عمليات الانضمام والاستعلام الفرعي في الجزء الرئيسي من التحديد)
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
في كل هذه العينات، أريد الاستعلام عن 200 صف لكل صفحة وأقوم بإحضار الصف للصفحة رقم 1200.
في SQL Server 2008، يمكنك استخدام مفهوم CTE.ولهذا السبب، قمت بكتابة نوعين من الاستعلامات لـ SQL server 2008+
- SQL خادم 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
والحل الثاني مع CTE في خادم SQL 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.
;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 خادم 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;
جرب هذا النهج:
SELECT TOP @offset a.*
FROM (select top @limit b.*, COUNT(*) OVER() totalrows
from TABLENAME b order by id asc) a
ORDER BY id desc;
يبدو أن استخدام الحالة الحكيمة سهل الاستخدام وسريع، فقط قم بتعيين رقم الصفحة.
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
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)
حسنًا، لقد استخدمت نموذج الاستعلام التالي في قاعدة بيانات 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.
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
سيتم إعادة تشغيل idx عندما يتعلق الأمر بـ init_id مختلف
ل ROW_NUMBER
التقنية، إذا لم يكن لديك عمود فرز لاستخدامه، فيمكنك استخدام CURRENT_TIMESTAMP
على النحو التالي:
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
لقد نجح هذا الأمر جيدًا بالنسبة لي في عمليات البحث على جداول بأحجام تصل إلى 700000.
يؤدي هذا إلى جلب السجلات من 11 إلى 30.
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
يمنحك هذا الجزء القدرة على ترقيم الصفحات باستخدام SQL Server والإصدارات الأحدث من MySQL ويحمل إجمالي عدد الصفوف في كل صف.يستخدم مفتاحك الأساسي لحساب عدد الصفوف الفريدة.
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
لم تحدد اللغة ولا برنامج التشغيل الذي تستخدمه.لذلك أنا أصف ذلك بشكل تجريدي.
- قم بإنشاء مجموعة نتائج/مجموعة بيانات قابلة للتمرير.هذا يتطلب أساسيًا على الجدول (الجداول)
- القفز حتى النهاية
- طلب عدد الصفوف
- انتقل إلى بداية الصفحة
- قم بالتمرير عبر الصفوف حتى نهاية الصفحة