本文作者:草上飞
网址:
www.newbooks.com.cn
QQ:1469886
如需转载,请保留以上信息。
谢谢!
点击下载支持多表关联任意字段排序的存储过程分页SQL>>>
网上有很多现成的存储过程分页sql,但是大多数只支持主键字段或者唯一值字段进行排序。而对于有重复值的字段进行排序的时候,数据会遗漏。
而且很多存储过程分页脚本也不支持多表关联查询的分页,而我们现实应用中,一般都是多表关联的查询,针对这几个问题,我网上随便找了一个
现成的脚本,进行了一下修改。修改后的脚本支持多表查询和任意字段排序(包括数值型字段)。
以下脚本注释以我开发的新书城网上书店(www.newbooks.com.cn)为例进行注释。
本存储过程分页的主要思路是,排序的同时引入主键字段,如果排序字段值重复的时候,来利用排序字段值相等,但是主键不相等的条件来取记录,具体以price字段升序排序为例进行讲解:
1.先取得(@PageIndex-1)*@PageSize条记录中的price字段和主键字段。这些记录的顺序按照price升序和主键升序。
相关sql伪代码为:select top (@PageIndex-1)*@PageSize tblbooks.price,tblbooks.bookid from tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid
2.从上面的记录中取得top 1记录,top 1记录按照price降序和主键降序。其实就是取得上面记录中的最后一条记录,将这条记录的price字段和主键字段的值赋值给2个临时变量。
相关sql伪代码为:
select top 1 @orderFldValue=@orderFldName,@keyFldValue=@fldName from (select top (@PageIndex-1)*@PageSize tblbooks.price,tblbooks.bookid from tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid)
3.我们取得上面2个值后,就可以把这2个值作为条件,来取得我们的分页数据了。思路就是top 20 ... where price>取出来的price or (price=取出来的price and 主键bookid>取出来的主键值)
相关sql伪代码为:
select top 20 @listFldName from @tblName where @strWhere and (price>@orderFldValue or (price=@orderFldValue and bookid>@keyFldValue))
从而我们取出了分页数据。
调用的代码如下:
exec GetRecordFromPage "tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid","tblbooks.bookid","tblbooks.bookid,tblbooks.bookname,tblbooks.price",
"tblbooks.price","",20,3,0," tblbooktypes.typecode like '0.1.20%'"
本存储过程sql语句如下:
/**/
/*
参数说明: @tblName 需要查询的表名。如图书表tblbooks 。如果是多表(图书表关联图书分类表)则写成:tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid
@fldName 主键字段名 bookid
@listFldName 需要查询的字段。如:书名(tblbooks.bookname)、作者(tblbooks.author)、价格(tblbooks.price)
@orderFldName 需要排序的字段。 如(tblbooks.price) 我们以非主键且有重复字段价格字段进行排序
@orderFldType 需要排序的字段的类型。 因为price这段类型为float,所以我们这里设置值为"float"。
@PageSize 每页记录数
@PageIndex 要获取的页码
@OrderType 排序类型, 0 - 升序, 1 - 降序
@strWhere 查询条件 (注意: 不要加 where)
作者:草上飞
Q Q:1469886
说明:本存储过程为在优化新书城网上书店(www.newbooks.com.cn)的分页时候整理出来的。本存储过程可以任意转载,但在转载过程中请保留以上信息。谢谢!
新书城网上书店(www.newbooks.com.cn)现有30几万的图书数量,利用该存储过程达到了根据价格、销量、出版日期等字段快速排序的效果,具体分页速度可进入该网站进行查看。
如对该存储过程有疑问,请与本人联系。
*/


CREATE
PROCEDURE
GetRecordFromPage
@tblName
varchar
(
500
),
@fldName
varchar
(
50
),
@listFldName
varchar
(
255
),
@orderFldName
varchar
(
50
),
@orderFldType
varchar
(
50
),
@PageSize
int
=
10
,
@PageIndex
int
=
1
,
@OrderType
bit
=
0
,
@strWhere
varchar
(
2000
)
=
''
AS

declare
@strSQL
nvarchar
(
4000
)
--
主语句
declare
@strTmp
varchar
(
1000
)
--
临时变量
declare
@strOrder
varchar
(
500
)
--
排序类型
declare
@strOrder2
varchar
(
500
)
--
declare
@orderFldValue
nvarchar
(
100
)
--
排序字段对应的值
declare
@keyFldValue
nvarchar
(
100
)
--
主键字段对应的值 add
declare
@operator
char
(
1
)
--
add by caoy
declare
@tempValueSql
varchar
(
100
)
declare
@strOrderby
varchar
(
5
)
if
(
@orderFldType
=
'
float
'
)
set
@tempValueSql
=
'
cast(@orderFldValue as float)
'
else
set
@tempValueSql
=
'
@orderFldValue
'

--
获取表明 。
declare
@tablename
varchar
(
20
)
if
charindex
(
'
.
'
,
@orderFldName
)
>
1
set
@tablename
=
left
(
@orderFldName
,
charindex
(
'
.
'
,
@orderFldName
)
-
1
)
else
set
@tablename
=
@orderFldName
if
@OrderType
!=
0
begin
set
@operator
=
'
<
'
set
@strOrderby
=
'
desc
'
set
@strOrder2
=
'
asc
'
end
else
begin
set
@operator
=
'
>
'
set
@strOrderby
=
'
asc
'
set
@strOrder2
=
'
desc
'
end
set
@strOrder
=
'
order by
'
+
@orderFldName
+
@strOrderby
if
@fldName
!=
@orderFldName
--
如果排序字段不是主键字段,则增加主键排序
set
@strOrder
=
@strOrder
+
'
,
'
+
@fldName
+
@strOrderby
--
先得到orderFldValue和keyValue

set
@strSQL
=
'
select top 1 @orderFldValue=convert(nvarchar(100),
'
+
@orderFldName
+
'
,20)
'
/**/
/***注意,如果需要排序的字段的值长度超过Nvarchar(100),请修改此处***********/
if
@fldName
!=
@orderFldName
set
@strSQL
=
@strSQL
+
'
,@keyFldValue=
'
+
@fldName
else
set
@strSQL
=
@strSQL
+
'
,@keyFldValue=1
'
set
@strSQL
=
@strSQL
+
'
from (select top
'
+
str
((
@PageIndex
-
1
)
*
@PageSize
)
+
'
'
+
@orderFldName
if
@fldName
!=
@orderFldName
--
add by caoy
set
@strSQL
=
@strSQL
+
'
,
'
+
@fldName
set
@strSQL
=
@strSQL
+
'
from
'
+
@tblName
+
''
if
@strWhere
!=
''
set
@strSQL
=
@strSQL
+
'
where
'
+
@strWhere
set
@strSQL
=
@strSQL
+
@strOrder
+
'
) as
'
+
@tablename
+
'
order by
'
+
@orderFldName
+
@strOrder2
if
@fldName
!=
@orderFldName
--
add by caoy
set
@strSQL
=
@strSQL
+
'
,
'
+
@fldName
+
@strOrder2
--
print @strSQL

exec
sp_executesql
@strSQL
,N
'
@orderFldValue nvarchar(100) output,@keyFldValue nvarchar(100) output
'
,
@orderFldValue
output,
@keyFldValue
output
/**/
/***注意,如果需要排序的字段的值长度超过Nvarchar(100),请修改此处***********/
--
得到排序字段值和主键值结束


if
@PageIndex
=
1
begin
set
@strTmp
=
''
if
@strWhere
!=
''
set
@strTmp
=
'
where (
'
+
@strWhere
+
'
)
'

set
@strSQL
=
'
select top
'
+
str
(
@PageSize
)
+
'
'
+
@listFldName
+
'
from
'
+
@tblName
+
''
+
@strTmp
+
'
'
+
@strOrder
exec
(
@strSQL
)
end
else
begin
--
取得top数据并返回
set
@strSQL
=
N
'
select top
'
+
str
(
@PageSize
)
+
'
'
+
@listFldName
+
'
from
'
+
@tblName
+
'
where (
'
+
@orderFldName
+
@operator
+
@tempValueSql
+
'
and @keyFldValue=@keyFldValue
'
if
@fldName
!=
@orderFldName
--
add by caoy
set
@strSQL
=
@strSQL
+
'
or (
'
+
@orderFldName
+
'
=
'
+
@tempValueSql
+
'
and
'
+
@fldName
+
@operator
+
'
@keyFldValue)) and (1=1
'
if
@strWhere
!=
''
set
@strSQL
=
@strSQL
+
'
and
'
+
@strWhere
set
@strSQL
=
@strSQL
+
'
)
'
+
@strOrder
if
@fldName
=
@orderFldName
set
@keyFldValue
=
1
--
print @strSQL
exec
sp_executesql
@strSQL
,N
'
@orderFldValue nvarchar(100),@keyFldValue nvarchar(100)
'
,
@orderFldValue
,
@keyFldValue

end

SET
QUOTED_IDENTIFIER
OFF
GO
|
|