游标的问题

buzhunmeiyouni 2017-11-15 05:38:06
CREATE PROC p_a
AS
begin
DECLARE @fname VARCHAR(255)
DECLARE @sql VARCHAR(max)
DECLARE table_lange cursor for
select fname from t_emp
open table_lange
fetch next from table_lange into @Fname--匹配第一条记录
while (@@FETCH_STATUS=0)-- 读取游标状态,循环
begin
SET @sql='SELECT a.FOfferItem,a.FUnit,a.FQty,a.FSupplier,a.FNOTE
,ISNULL(CASE WHEN c.fname = '''+@fname+''' THEN CONVERT(VARCHAR(50),FPrice*FQty) End,'''') '''+@fname+'''
FROM LGEntry_OfferSheet a
INNER JOIN LGBOS_OfferSheet b ON a.fid = b.FID
INNER JOIN t_emp c ON c.fitemid = b.FOfficeClerk
WHERE c.fname IN (SELECT c.fname FROM t_emp)
EXEC (@sql)
FETCH next from table_lange into @Fname
END
CLOSE table_lange
DEALLOCATE table_lange
END
结果是这样的
'
怎么写才能实现这样的结果


...全文
554 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
buzhunmeiyouni 2017-11-16
  • 打赏
  • 举报
回复
引用 16 楼 qq_37170555 的回复:
[quote=引用 15 楼 buzhunmeiyouni 的回复:] 第二种方法写出来了,就是应为fname 的值不确定,所以才想用变量的方法来写的
第二种方法也可以写成动态的,按上面那样先把数据插入#tab表中,然后用下面的脚本

DECLARE @sql VARCHAR(max)
SET @sql = 
    'select [FOfferItem],
		[FUnit],
		[FQty],
		[FSupplier],
		[FNOTE]'

SELECT @sql = @sql + ',max(case fname when ''' + fname + 
       ''' then sum_price else null end)[' + fname + ']'
FROM   (
           SELECT DISTINCT fname
           FROM   #tab
       ) a

SET @sql = @sql + 
    ' from #tab group by [FOfferItem],
		[FUnit],
		[FQty],
		[FSupplier],
		[FNOTE]'

PRINT @sql
EXEC (@sql)

[/quote] 可以了,谢谢,辛苦了
xiaoxiangqing 2017-11-16
  • 打赏
  • 举报
回复
复杂逻辑才用游标
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 15 楼 buzhunmeiyouni 的回复:
第二种方法写出来了,就是应为fname 的值不确定,所以才想用变量的方法来写的
第二种方法也可以写成动态的,按上面那样先把数据插入#tab表中,然后用下面的脚本

DECLARE @sql VARCHAR(max)
SET @sql = 
    'select [FOfferItem],
		[FUnit],
		[FQty],
		[FSupplier],
		[FNOTE]'

SELECT @sql = @sql + ',max(case fname when ''' + fname + 
       ''' then sum_price else null end)[' + fname + ']'
FROM   (
           SELECT DISTINCT fname
           FROM   #tab
       ) a

SET @sql = @sql + 
    ' from #tab group by [FOfferItem],
		[FUnit],
		[FQty],
		[FSupplier],
		[FNOTE]'

PRINT @sql
EXEC (@sql)

buzhunmeiyouni 2017-11-16
  • 打赏
  • 举报
回复
第二种方法写出来了,就是应为fname 的值不确定,所以才想用变量的方法来写的
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 13 楼 buzhunmeiyouni 的回复:
FOfferItem FUnit FQty FSupplier FNOTE fname sum_price 256 252 10.0000000000 264 147 李四 100.00000000000 259 252 2000.0000000000 263 001 1800000.00000000000 0 0 0.0000000000 0 001 0.00000000000 259 252 2000.0000000000 264 002 0.00000000000 0 0 0.0000000000 0 002 0.00000000000 255 252 1000.0000000000 263 张三 1000000.00000000000 0 0 0.0000000000 0 张三 0.00000000000 255 252 20.0000000000 262 123 李四 200.00000000000

use Tempdb
go
--> --> 听雨停了-->测试数据
 
if not object_id(N'Tempdb..#tab') is null
	drop table #tab
Go
Create table #tab([FOfferItem] int,[FUnit] int,[FQty] decimal(18,10),[FSupplier] int,[FNOTE] nvarchar(23),[fname] nvarchar(39),[sum_price] NVARCHAR(50))
Insert #tab
select 256,252,10.0000000000,264,N'147',N'李四','100.00000000000' union all
select 259,252,2000.0000000000,263,N'001',N'1800000.00000000000',null union all
select 0,0,0.0000000000,0,N'001',N'0.00000000000',null union all
select 259,252,2000.0000000000,264,N'002',N'0.00000000000',null union all
select 0,0,0.0000000000,0,N'002',N'0.00000000000',null union all
select 255,252,1000.0000000000,263,N'张三',N'1000000.00000000000',null union all
select 0,0,0.0000000000,0,N'张三',N'0.00000000000',null union all
select 255,252,20.0000000000,262,N'123',N'李四',200.00000000000
--测试数据结束

--方法1
SELECT *
FROM   #tab PIVOT(MAX(sum_price) FOR fname IN ([001],[002],[李四],[张三]))a


--方法2
SELECT [FOfferItem],
		[FUnit],
		[FQty],
		[FSupplier],
		[FNOTE],
       MAX(CASE fname WHEN '001' THEN sum_price ELSE null END) [001],
       MAX(CASE fname WHEN '002' THEN sum_price ELSE null END) [002],
       MAX(CASE fname WHEN '李四' THEN sum_price ELSE null END) [李四],
       MAX(CASE fname WHEN '张三' THEN sum_price ELSE null END) [张三]
FROM   #tab
GROUP BY
       [FOfferItem],
		[FUnit],
		[FQty],
		[FSupplier],
		[FNOTE]
在我这边是可以出来的 ,第一种方法出不来可能是你sql版本的 问题,你用第二种试试看
buzhunmeiyouni 2017-11-16
  • 打赏
  • 举报
回复
FOfferItem FUnit FQty FSupplier FNOTE fname sum_price 256 252 10.0000000000 264 147 李四 100.00000000000 259 252 2000.0000000000 263 001 1800000.00000000000 0 0 0.0000000000 0 001 0.00000000000 259 252 2000.0000000000 264 002 0.00000000000 0 0 0.0000000000 0 002 0.00000000000 255 252 1000.0000000000 263 张三 1000000.00000000000 0 0 0.0000000000 0 张三 0.00000000000 255 252 20.0000000000 262 123 李四 200.00000000000
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 9 楼 buzhunmeiyouni 的回复:
再不行的话你就把#tab中的数据复制贴出来,带上字段一起贴出来。我这边帮你执行下看看
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 9 楼 buzhunmeiyouni 的回复:
把打印出来的这句sql执行执行下看看,不应该会报错的啊,就是这样的
buzhunmeiyouni 2017-11-16
  • 打赏
  • 举报
回复
引用 10 楼 qq_37170555 的回复:
[quote=引用 9 楼 buzhunmeiyouni 的回复:]
把打印出来的这句sql执行执行下看看,不应该会报错的啊,就是这样的[/quote] 执行过了,报的是同样的错误
buzhunmeiyouni 2017-11-16
  • 打赏
  • 举报
回复
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 5 楼 buzhunmeiyouni 的回复:
[quote=引用 4 楼 qq_37170555 的回复:] [quote=引用 2 楼 buzhunmeiyouni 的回复:] [quote=引用 1 楼 qq_37170555 的回复:] 再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件
怎么存储啊,不是很理解[/quote] 看了楼上RanK_1的方法,我又认真的看了一遍你Sql的业务逻辑,大概明白了你需要做什么了。其实确实不需要用游标去弄,搞得这么复杂,一开始还以为你要干嘛呢。不过楼上那样写也是不行的,可能他还没认真看你的业务逻辑。其实就是一个行转列显示的需求,通过下面的代码就可以实现,你可以试试看

--把以下查询结果插入临时表#tab
SELECT a.FOfferItem,
       a.FUnit,
       a.FQty,
       a.FSupplier,
       a.FNOTE,
       c.fname,
       --FPrice * FQty这个前面最好都写上表的别名,也就是到底是a.FPrice还是b.FPrice
       ISNULL(CONVERT(VARCHAR(50), FPrice * FQty),'') AS sum_price
INTO #tab       
FROM   LGEntry_OfferSheet a
       INNER JOIN LGBOS_OfferSheet b
            ON  a.fid = b.FID
       INNER JOIN t_emp c
            ON  c.fitemid = b.FOfficeClerk

--实现行转列显示
DECLARE @name     VARCHAR(MAX),
        @sql      VARCHAR(MAX)

SET @name = STUFF(
        (
            SELECT DISTINCT ',[' + fname + ']'
            FROM   #tab FOR XML PATH('')
        ),
        1,
        1,
        ''
    )
PRINT @name

SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a'
PRINT @sql
EXEC (@sql)   
[/quote] 执行后报错[/quote]

--把以下查询结果插入临时表#tab
SELECT a.FOfferItem,
       a.FUnit,
       a.FQty,
       a.FSupplier,
       a.FNOTE,
       c.fname,
       --FPrice * FQty这个前面最好都写上表的别名,也就是到底是a.FPrice还是b.FPrice
       ISNULL(CONVERT(VARCHAR(50), FPrice * FQty),'') AS sum_price
INTO #tab       
FROM   LGEntry_OfferSheet a
       INNER JOIN LGBOS_OfferSheet b
            ON  a.fid = b.FID
       INNER JOIN t_emp c
            ON  c.fitemid = b.FOfficeClerk
PRINT  '插入临时表成功'

--实现行转列显示
DECLARE @name     VARCHAR(MAX),
        @sql      VARCHAR(MAX)

SET @name = STUFF(
        (
            SELECT DISTINCT ',[' + fname + ']'
            FROM   #tab FOR XML PATH('')
        ),
        1,
        1,
        ''
    )
PRINT @name

SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a'
PRINT @sql
EXEC (@sql)   

这样执行下,把打印的内容截图出来看看
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 5 楼 buzhunmeiyouni 的回复:
[quote=引用 4 楼 qq_37170555 的回复:] [quote=引用 2 楼 buzhunmeiyouni 的回复:] [quote=引用 1 楼 qq_37170555 的回复:] 再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件
怎么存储啊,不是很理解[/quote] 看了楼上RanK_1的方法,我又认真的看了一遍你Sql的业务逻辑,大概明白了你需要做什么了。其实确实不需要用游标去弄,搞得这么复杂,一开始还以为你要干嘛呢。不过楼上那样写也是不行的,可能他还没认真看你的业务逻辑。其实就是一个行转列显示的需求,通过下面的代码就可以实现,你可以试试看

--把以下查询结果插入临时表#tab
SELECT a.FOfferItem,
       a.FUnit,
       a.FQty,
       a.FSupplier,
       a.FNOTE,
       c.fname,
       --FPrice * FQty这个前面最好都写上表的别名,也就是到底是a.FPrice还是b.FPrice
       ISNULL(CONVERT(VARCHAR(50), FPrice * FQty),'') AS sum_price
INTO #tab       
FROM   LGEntry_OfferSheet a
       INNER JOIN LGBOS_OfferSheet b
            ON  a.fid = b.FID
       INNER JOIN t_emp c
            ON  c.fitemid = b.FOfficeClerk

--实现行转列显示
DECLARE @name     VARCHAR(MAX),
        @sql      VARCHAR(MAX)

SET @name = STUFF(
        (
            SELECT DISTINCT ',[' + fname + ']'
            FROM   #tab FOR XML PATH('')
        ),
        1,
        1,
        ''
    )
PRINT @name

SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a'
PRINT @sql
EXEC (@sql)   
[/quote] 执行后报错[/quote] 把print @name和print @sql的值贴出来看看
听雨停了 2017-11-16
  • 打赏
  • 举报
回复
引用 5 楼 buzhunmeiyouni的回复:
[quote=引用 4 楼 qq_37170555 的回复:]
[quote=引用 2 楼 buzhunmeiyouni 的回复:]
[quote=引用 1 楼 qq_37170555 的回复:]
再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件


怎么存储啊,不是很理解[/quote]
看了楼上RanK_1的方法,我又认真的看了一遍你Sql的业务逻辑,大概明白了你需要做什么了。其实确实不需要用游标去弄,搞得这么复杂,一开始还以为你要干嘛呢。不过楼上那样写也是不行的,可能他还没认真看你的业务逻辑。其实就是一个行转列显示的需求,通过下面的代码就可以实现,你可以试试看

--把以下查询结果插入临时表#tab
SELECT a.FOfferItem,
a.FUnit,
a.FQty,
a.FSupplier,
a.FNOTE,
c.fname,
--FPrice * FQty这个前面最好都写上表的别名,也就是到底是a.FPrice还是b.FPrice
ISNULL(CONVERT(VARCHAR(50), FPrice * FQty),'') AS sum_price
INTO #tab
FROM LGEntry_OfferSheet a
INNER JOIN LGBOS_OfferSheet b
ON a.fid = b.FID
INNER JOIN t_emp c
ON c.fitemid = b.FOfficeClerk

--实现行转列显示
DECLARE @name VARCHAR(MAX),
@sql VARCHAR(MAX)

SET @name = STUFF(
(
SELECT DISTINCT ',[' + fname + ']'
FROM #tab FOR XML PATH('')
),
1,
1,
''
)
PRINT @name

SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a'
PRINT @sql
EXEC (@sql)
[/quote]

执行后报错[/quote] SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a' 在这个for前面加一个空格
buzhunmeiyouni 2017-11-16
  • 打赏
  • 举报
回复
引用 4 楼 qq_37170555 的回复:
[quote=引用 2 楼 buzhunmeiyouni 的回复:]
[quote=引用 1 楼 qq_37170555 的回复:]
再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件


怎么存储啊,不是很理解[/quote]
看了楼上RanK_1的方法,我又认真的看了一遍你Sql的业务逻辑,大概明白了你需要做什么了。其实确实不需要用游标去弄,搞得这么复杂,一开始还以为你要干嘛呢。不过楼上那样写也是不行的,可能他还没认真看你的业务逻辑。其实就是一个行转列显示的需求,通过下面的代码就可以实现,你可以试试看

--把以下查询结果插入临时表#tab
SELECT a.FOfferItem,
a.FUnit,
a.FQty,
a.FSupplier,
a.FNOTE,
c.fname,
--FPrice * FQty这个前面最好都写上表的别名,也就是到底是a.FPrice还是b.FPrice
ISNULL(CONVERT(VARCHAR(50), FPrice * FQty),'') AS sum_price
INTO #tab
FROM LGEntry_OfferSheet a
INNER JOIN LGBOS_OfferSheet b
ON a.fid = b.FID
INNER JOIN t_emp c
ON c.fitemid = b.FOfficeClerk

--实现行转列显示
DECLARE @name VARCHAR(MAX),
@sql VARCHAR(MAX)

SET @name = STUFF(
(
SELECT DISTINCT ',[' + fname + ']'
FROM #tab FOR XML PATH('')
),
1,
1,
''
)
PRINT @name

SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a'
PRINT @sql
EXEC (@sql)
[/quote]

执行后报错
听雨停了 2017-11-15
  • 打赏
  • 举报
回复
引用 2 楼 buzhunmeiyouni 的回复:
[quote=引用 1 楼 qq_37170555 的回复:] 再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件
怎么存储啊,不是很理解[/quote] 看了楼上RanK_1的方法,我又认真的看了一遍你Sql的业务逻辑,大概明白了你需要做什么了。其实确实不需要用游标去弄,搞得这么复杂,一开始还以为你要干嘛呢。不过楼上那样写也是不行的,可能他还没认真看你的业务逻辑。其实就是一个行转列显示的需求,通过下面的代码就可以实现,你可以试试看

--把以下查询结果插入临时表#tab
SELECT a.FOfferItem,
       a.FUnit,
       a.FQty,
       a.FSupplier,
       a.FNOTE,
       c.fname,
       --FPrice * FQty这个前面最好都写上表的别名,也就是到底是a.FPrice还是b.FPrice
       ISNULL(CONVERT(VARCHAR(50), FPrice * FQty),'') AS sum_price
INTO #tab       
FROM   LGEntry_OfferSheet a
       INNER JOIN LGBOS_OfferSheet b
            ON  a.fid = b.FID
       INNER JOIN t_emp c
            ON  c.fitemid = b.FOfficeClerk

--实现行转列显示
DECLARE @name     VARCHAR(MAX),
        @sql      VARCHAR(MAX)

SET @name = STUFF(
        (
            SELECT DISTINCT ',[' + fname + ']'
            FROM   #tab FOR XML PATH('')
        ),
        1,
        1,
        ''
    )
PRINT @name

SET @sql = 'SELECT * from #tab pivot(max(sum_price)for fname in(' + @name + '))a'
PRINT @sql
EXEC (@sql)   
RINK_1 2017-11-15
  • 打赏
  • 举报
回复
你为什么要用游标呢,用以下试试呢

declare @sql varchar(max)

select @sql=ISNULL(@sql+',','')+'case when c.fname='''+fname+''' then convert(varchar(50),FPrice*FQty) else '''' end as '+fname+''
from (select distinct fname from #t_emp) as A

set @sql='SELECT a.FOfferItem,a.FUnit,a.FQty,a.FSupplier,a.FNOTE,'+@sql+' 
          FROM LGEntry_OfferSheet a
          INNER JOIN LGBOS_OfferSheet b ON  a.fid = b.FID
          INNER JOIN t_emp c ON  c.fitemid = b.FOfficeClerk'
       
exec(@sql)
buzhunmeiyouni 2017-11-15
  • 打赏
  • 举报
回复
引用 1 楼 qq_37170555 的回复:
再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件
怎么存储啊,不是很理解
听雨停了 2017-11-15
  • 打赏
  • 举报
回复
再定义一个变量@all_sql用来存储每一次游标指针返回的@sql,同时写上关联条件

590

社区成员

发帖
与我相关
我的任务
社区描述
提出问题
其他 技术论坛(原bbs)
社区管理员
  • community_281
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧