使用函数及游标实现SQL多行转一列

有时候在一些系统中我们需要用SQL语句将一对多关系表中的数据以每条记录一行的形式进行显示。本文分别采用函数及游标的方法来实现该功能。
示例表描述如下
一张用户表及文档表

现在想实现如下功能,查询出每个用户及其对应的文档名称的综合,如下结果
userID                            userName                               DocNames
1                                    fengyan                            sql基础,asp.net入门
2                                    eflylab                                     精品美食

注意到最后一列是类似统计。这就决定不能使用left join做,那样1号用户会出现二行,不是期望的
其实很多时间需求是需要我们使用SQL完成这样的功能,而不是放在程序里!如果做?
这里可以写一个函数来完成该功能
复制代码

CREATE   function  f_getUserDocsByUserID( @userID   int
returns   varchar ( 8000
as  
begin  
declare   @str   varchar ( 8000
set   @str = ''  
select   @str = @str + ' , ' + docName  from  Doc  where  UserID = @userID  
if ( len ( @str ) > 1 )
    
set   @str =right ( @str , len ( @str ) - 1
return ( @str
复制代码
则相应的查询语句为
select  u. * ,study.dbo.f_getUserDocsByUserID(u.userID)  as  docs  from   [ user ]   as  u
运行效果

实现功能,这里仅以很简单的示例,演示了将多行转换成一列的需求,实际中针对docs的结果可能更复杂一些。
需要相应的变通!

第二种方式可以使用游标,这对于很多不理解和不会应用游标的朋友来说,可以学习一下!
复制代码
-- 定义结果集表变量
DECLARE   @t   TABLE (userID  varchar ( 10 ),userName  varchar ( 100 ),DocNames  varchar ( 8000 ))

-- 定义游标并进行合并处理
DECLARE  MyCURSOR  CURSOR   
FOR
SELECT  u. * ,d.docName  FROM   [ user ]  u  left   join   [ Doc ]  d  on  u.userID = d.userID   order   by  u.userID

DECLARE   @userID_old   int , @userID   int , @userName   varchar ( 50 ), @oldUserName   varchar ( 50 ), @docName   varchar ( 50 ), @s   varchar ( 100 )
-- 打开游标

OPEN  MyCURSOR
FETCH  MyCURSOR  INTO   @userID , @userName , @docName
SELECT   @userID_old = @userID , @s = '' , @oldUserName = @userName
WHILE   @@FETCH_STATUS = 0      -- 游标存在数据时循环
BEGIN
    
IF   @userID = @userID_old      -- 如果当前记录和上一条用户ID相同,则更改变量@s的值
         SELECT   @s = @s + ' , ' + @docName
    
ELSE
    
BEGIN      -- 否则 已经是下一位用户了,应该执行添加操作
         -- UserID改变的时候添加操作
         INSERT   @t   VALUES ( @userID_old , @oldUserName , STUFF ( @s , 1 , 1 , '' ))
        
-- 将新的文件名赋值给@s 并且更新@userID_old,@oldUserName
         SELECT   @s = ' , ' + @docName , @userID_old = @userID , @oldUserName = @userName
    
END
    
FETCH  MyCURSOR  INTO   @userID , @userName , @docName
END
INSERT   @t   VALUES ( @userID_old , @oldUserName , STUFF ( @s , 1 , 1 , '' ))
CLOSE  MyCURSOR
DEALLOCATE  MyCURSOR
-- 显示结果
SELECT   *   FROM   @t
复制代码

运行结果如下:

也达到预期,在这里使用了一条left join查询
SELECT  u. * ,d.docName  FROM   [ user ]  u  left   join   [ Doc ]  d  on  u.userID = d.userID   order   by  u.userID
它的执行结果如下:

在方法二中使用游标在这个结果表中循环。中间使用一个变量结果表@t将结果存入@t中,最后@t即为所需结果
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值