我不擅长sql,但是我必须在我的存储过程中为jqGrid做分页,它有很多记录。我的asp.net mvc3控制器代码如下,
[HttpPost]
public JsonResult GetExtraPersons(int cId, long pId, JQGridSettings gridSettings)
{
List<ExtraPerson> extraPersons = new List<ExtraPerson>();
ExtraPersonViewModel extraPersonViewModel = new ExtraPersonViewModel();
extraPersonViewModel.CampId = cId;
extraPersonViewModel.ReferencePatientId = pId;
extraPersons = ExtraPersonService.GetExtraPersons(extraPersonViewModel.CampId, extraPersonViewModel.ReferencePatientId);
int pageIndex = gridSettings.pageIndex;
int pageSize = gridSettings.pageSize;
int totalRecords = extraPersons.Count;
int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
int startRow = (pageIndex - 1) * pageSize;
int endRow = startRow + pageSize;
var jsonData = new
{
total = totalPages,
page = pageIndex,
records = totalRecords,
rows =
(
extraPersons.Select(e => new
{
Id = e.ExtraPersonId,
FirstName = e.FirstName,
LastName = e.LastName,
MobilePhone = e.MobileNumber,
Email = e.EmailId,
PersonalNumber = e.PersonNumber,
Diabetes = e.Diabetes,
BloodPressure = e.BloodPressure,
})
).ToArray()
};
return Json(jsonData);
}
以及我在sql server 2008中的存储过程如下,
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetExtraPerson]
(
@CampId INT,
@ReferencePatientId BIGINT
)
AS
BEGIN
SET NOCOUNT ON
SELECT
PERS.PersonId,
PERS.FirstName,
PERS.LastName,
PERS.MobileNumber,
PERS.EmailId,
PERS.PersonNumber,
E.ExtraPersonId,
E.Diabetes,
E.BloodPressure
FROM
ExtraPerson E
INNER JOIN Person PERS
ON PERS.PersonId=E.PersonId
WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId AND E.IsDeleted = 0
END
现在jqGrid正常工作,除了分页。例如:如果它有15条记录,第一页显示10条记录,剩下的是第二页,但我不能去。 任何人都可以建议我,如何为jqgrid做分页?
答案 0 :(得分:2)
有很多方法可以实现您需要的STORED PROCEDURE
。例如,您可以在CTE SQL语句中使用ROW_NUMBER
构造。
如果您使用SQL Server 2012,则可以在OFFSET
之后使用FETCH
和ORDER BY
来实现分页(请参阅here)。在这种情况下,SQL语句看起来非常接近使用OFFSET
和LIMIT
的相应MySQL或PostgreSQL语句。顺便说一句,Microsoft Entity Framework使用Entity SQL Language具有紧密结构(SKIP
和LIMIT
)。如果您使用SQL Server 2012或更高版本,则可能首选OFFSET
和FETCH
。
因为您在问题中包含了SQL Server 2008标记,所以在我的回答中我不会使用新的SQL Server 2012结构。
另一个好方法是使用sp_executesql
,它允许您将SQL语句构造为带参数的字符串。它允许重用执行计划,这对于获得最佳性能非常重要。该方法允许您扩展STORED PROCEDURE
的代码以实现服务器端过滤(搜索)。
我看到需要在SQL语句中实现包含返回数据的ID(在您的情况下为PersonId
)的分页。因此,我决定建议您使用SELECT TOP
与LEFT OUTER JOIN
结合使用的简化方式。
您STORED PROCEDURE
dbo.GetExtraPerson
可以有两个int
类型的附加参数:@skip
和@pageSize
。如果@skip
等于0
,则STORED PROCEDURE
可以执行
SELECT TOP (@pageSize) PERS.PersonId
,PERS.FirstName
,PERS.LastName
,PERS.MobileNumber
,PERS.EmailId
,PERS.PersonNumber
,E.ExtraPersonId
,E.Diabetes
,E.BloodPressure
FROM ExtraPerson E
INNER JOIN Person PERS ON PERS.PersonId=E.PersonId
WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId AND E.IsDeleted=0
如果@skip
不等于0
,则相应的SQL语句可以是以下
WITH GetAll AS (
SELECT PERS.PersonId
,PERS.FirstName
,PERS.LastName
,PERS.MobileNumber
,PERS.EmailId
,PERS.PersonNumber
,E.ExtraPersonId
,E.Diabetes
,E.BloodPressure
FROM ExtraPerson E
INNER JOIN Person PERS ON PERS.PersonId=E.PersonId
WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId AND E.IsDeleted=0
),GetFirst AS (
SELECT TOP (@skip) *
FROM GetAll
ORDER BY Name
),GetNext AS (
SELECT TOP (@pageSize) a.*
FROM GetAll AS a
LEFT OUTER JOIN GetFirst AS f ON f.Id=a.Id
WHERE f.Id IS NULL
ORDER BY Name
)
SELECT * FROM GetNext
dbo.GetExtraPerson
的完整代码可以是以下
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE dbo.GetExtraPerson
@CampId int,
@ReferencePatientId bigint,
@skip int,
@pageSize int
AS
BEGIN
DECLARE @records int;
SET NOCOUNT ON;
SET @records = (SELECT COUNT(*)
FROM ExtraPerson E
INNER JOIN Person PERS ON PERS.PersonId=E.PersonId
WHERE E.CampId=@CampId
AND ReferencePatientId=@ReferencePatientId
AND E.IsDeleted=0);
IF @skip <= 0
SELECT TOP (@pageSize) PERS.PersonId
,PERS.FirstName
,PERS.LastName
,PERS.MobileNumber
,PERS.EmailId
,PERS.PersonNumber
,E.ExtraPersonId
,E.Diabetes
,E.BloodPressure
FROM ExtraPerson E
INNER JOIN Person PERS ON PERS.PersonId=E.PersonId
WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId
AND E.IsDeleted=0
ELSE
WITH GetAll AS (
SELECT PERS.PersonId
,PERS.FirstName
,PERS.LastName
,PERS.MobileNumber
,PERS.EmailId
,PERS.PersonNumber
,E.ExtraPersonId
,E.Diabetes
,E.BloodPressure
FROM ExtraPerson E
INNER JOIN Person PERS ON PERS.PersonId=E.PersonId
WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId
AND E.IsDeleted=0
),GetFirst AS (
SELECT TOP (@skip) *
FROM GetAll
ORDER BY Name
),GetNext AS (
SELECT TOP (@pageSize) a.*
FROM GetAll AS a
LEFT OUTER JOIN GetFirst AS f ON f.Id=a.Id
WHERE f.Id IS NULL
ORDER BY Name
)
SELECT * FROM GetNext;
RETURN @records;
END
GO
上述步骤另外返回记录总数,您可以使用它来指定totalRecords
值。
如果您将上述代码与sp_executesql
结合使用,则可以轻松修改代码以在所有ORDER BY
语句中包含SELECT TOP
,以便返回的值对应于请求的排序顺序jqGrid中的用户。