Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 415|回复: 0

用视图+存储过程解决复杂查询的排序分页问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-9-3 14:21:17 | 显示全部楼层 |阅读模式

    数据库中复杂的联查+筛选条件+排序+分页一直是比较头疼的问题

     

    为了模拟这个问题,首先建立两个表

    create table t_userType (
        id int identity(1,1) not null primary key,
        name varchar(50)
    )
    GO
    
    create table t_user (
        id int identity(1,1) not null primary key,
        t_userTypeId int not null,
        name varchar(50),
        foreign key (t_userTypeId) references t_userType(id)
    )
    GO

     

    下面插入一些测试数据

      

     

    在t_user这个表中,t_userTypeId字段关联到了t_userType这个表

    我们希望在查询用户时,同时查询到这个用户类型的name,可以通过联查实现

    select u.*, t.name as typeName
        from t_user u
        inner join t_userType t
        on t.id = u.t_userTypeId

     

    如果联查的表多了,就会比较复杂,所以建立一个视图

    create view view_user_andType
    as
        select u.*, t.name as typeName
        from t_user u
        inner join t_userType t
        on t.id = u.t_userTypeId
    go

     

    这时,使用下面的语句,就能得到我们想要的结果

    select * from view_user_andType

     

    如果想提供分页功能的话,需要这样写

    select top 5 * from view_user_andType where id not in (select id top 0 view_user_andType)

     

    加入条件过滤和排序

    select top 5 * from view_user_andType 
    where id>1 and 
        id not in (
            select top 0 id view_user_andType 
            where id>1 order by id) 
    order by id

     

    如果每个表的联查都写成这样,也是比较头大的

    所以通过一个存储过程,封装分页和排序逻辑

    -- 存储过程:通用分页
    --
    -- 分页查询某个表或视图
    --
    -- 参数列表:
    --        srcTableName:视图或表名
    --        idColumnName:主键列名
    --        pageSize:每页长度(1~n)
    --        pageIndex:页码(1~n)
    --        condition:过滤条件
    --        orderBy:排序方式,必须为查询结果中的字段名
    --        isDesc:是否倒序,可选值(true, false)
    --
    SET QUOTED_IDENTIFIER ON 
    GO
    SET ANSI_NULLS ON 
    GO
    IF OBJECT_ID ( 'proc_selectByPage', 'P' ) IS NOT NULL 
        Drop PROCEDURE [proc_selectByPage];
    GO
    create  procedure [dbo].[proc_selectByPage]
        @srcTableName varchar(50),
        @idColumnName varchar(50) = 'id',
        @pageSize int = 10,
        @pageIndex int = 1,
        @condition varchar(500) = '',
        @orderBy varchar(50),
        @isDesc varchar(50) = 'false'
    AS
    begin
    
        -- 参数容错
        if (@pageIndex <= 0)
        begin
            set @pageIndex = 1
        end
    
        -- 组装语句
        declare @sql1 varchar(4000)
        set @sql1 = 'select top ' + cast (@pageSize as varchar(50)) + 
                    ' * from ' + @srcTableName +
                    ' where (' + @idColumnName +
                            ' not in (select top ' + cast ((@pageSize * (@pageIndex-1)) as varchar(50)) +
                            ' ' + @idColumnName +
                            ' from ' + @srcTableName
        
        if ( @condition <> '' )
        begin
            set @sql1 = @sql1 + ' where ' + @condition
        end
                            
        set @sql1 = @sql1 + ' order by ' + @orderBy
                            
        if ( @isDesc = 'true' ) 
        begin 
            set @sql1 = @sql1 + ' desc ';
        end
        else if ( @isDesc = 'false' )
        begin
            set @sql1 = @sql1 + ' asc ';
        end
    
        set @sql1 = @sql1 + '  ) '
        
        if ( @condition <> '' )
        begin
            set @sql1 = @sql1 + ' and ' + @condition
        end
        
        set @sql1 = @sql1 + ')'
        
        set @sql1 = @sql1 + ' order by ' + @orderBy
        
        if ( @isDesc = 'true' ) 
        begin 
            set @sql1 = @sql1 + ' desc ';
        end
        else if ( @isDesc = 'false' )
        begin
            set @sql1 = @sql1 + ' asc ';
        end
        
        -- 输出语句,并执行
        print @sql1
        exec(@sql1)
    
    end
    GO
    SET QUOTED_IDENTIFIER OFF 
    GO
    SET ANSI_NULLS ON 
    GO

     

    再实现相同的功能就可以这样写

    exec proc_selectByPage 'view_user_andType', 'id', 3, 2, '', 'name', 'false'

     

    可以兼容表或视图的分页,sqlserver2000下测试通过

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-1 09:40 , Processed in 0.074144 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表