来个有点挑战性的题目

guguda2008 2009-08-29 09:44:01
昨天写程序的时候遇到个小问题,发出来与大家分享
我的程序中有一个表,是根据SQL动态生成的,SQL也是不固定的,有可能是
SELECT A,B,C FROM TB
也有可能是
SELECT D,E,F,G FROM TB2
而且列的类型和位置不一定,结果有可能是
A 1 B
C 2 D
也有可能是
1 A 2 B
3 C 4 D
现在能得到这个SQL语句,想用一个存储过程或者是别的什么对它进行处理,得到结果集中数字列的合计,字符串列设为空。
也就是说,对SELECT A,B,C FROM TB进行处理后得到
_ 3 _
对SELECT D,E,F,G FROM TB2进行处理后得到
4 _ 6 _
注意,这个SQL是很复杂的,SELECT出来的列都是多表计算出来的结果。

问题大概就是这样了,虽然已经用别的方法实现了,但我还是在想如何用SQL实现。高手们能帮我想想如何实现吗?
欢迎讨论,祝大家周末愉快~~
...全文
218 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
武哥博文 2009-08-31
  • 打赏
  • 举报
回复
顶一下
SQL77 2009-08-31
  • 打赏
  • 举报
回复
顶起,学习
guguda2008 2009-08-31
  • 打赏
  • 举报
回复
周一人多,看看有没有人写
黄_瓜 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 guguda2008 的回复:]
引用 20 楼 josy 的回复:
引用 17 楼 guguda2008 的回复:
引用 12 楼 josy 的回复:
既然这样,我就先来献个丑吧
SQL code--->测试数据ifobject_id('[tb]')isnotnulldroptable[tb]gocreatetable[tb]([col1]varchar(1),[col2]int,[col3]varchar(1),[col4] numeric(2,1))insert[tb]select'a',1,'b',3unionallselect'c',5,'d',3.5--->查询declare@sqlvarchar(8000)select@sql=isnull(@sql+',','')+'sum(['+a.name+']) as ['+a.name+']'from
  syscolumns a,systypes bwhere
  a.xtype=b.xtypeand
  a.id=object_id('tb')and
  b.namein('tinyint','smallint','decimal','int','real','money','float','bigint','numeric','smallmoney')orderby colidset@sql='select'+@sql+' from tb'exec(@sql)/**
col2        col4                                   
----------- ----------------------------------------
6          6.5
**/

树哥这个可以实现对单表的数字列合计查询,但是如果是这样的语句

SELECT A.ID,SUM(B.PRICE+A.COL1) 'TOTAL'
FROM (SELECT ID,SUM(COL1) 'COL1' FROM TB GROUP BY ID) A
LEFT JOIN TB1 B ON A.ID=B.AID AND YEAR(B.DATE) LIKE 2009
GROUP BY A.ID

呢?SYSCOLUMNS表里能取到这样的列吗?


这种需求本身是不符合常理的,连字段都不知道的去统计它基本上没啥意义
它统计出来的就是一个数字,这数字是怎么得来的,是否正确都无法验证

如果真要统计,可以把查询的结果插入到临时表里,这样也是对一个表进行判断和操作

呵呵知道了,看来是我胡思乱想了。
当时的第一想法是用SELECT INTO生成#表,但#表的列类型不会获取,所以才有这个问题。
[/Quote]
胡思乱想的人结贴吧,我和树哥三七分咋样?
guguda2008 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 josy 的回复:]
引用 17 楼 guguda2008 的回复:
引用 12 楼 josy 的回复:
既然这样,我就先来献个丑吧
SQL code--->测试数据ifobject_id('[tb]')isnotnulldroptable[tb]gocreatetable[tb]([col1]varchar(1),[col2]int,[col3]varchar(1),[col4] numeric(2,1))insert[tb]select'a',1,'b',3unionallselect'c',5,'d',3.5--->查询declare@sqlvarchar(8000)select@sql=isnull(@sql+',','')+'sum(['+a.name+']) as ['+a.name+']'from
  syscolumns a,systypes bwhere
  a.xtype=b.xtypeand
  a.id=object_id('tb')and
  b.namein('tinyint','smallint','decimal','int','real','money','float','bigint','numeric','smallmoney')orderby colidset@sql='select'+@sql+' from tb'exec(@sql)/**
col2        col4                                   
----------- ----------------------------------------
6          6.5
**/

树哥这个可以实现对单表的数字列合计查询,但是如果是这样的语句

SELECT A.ID,SUM(B.PRICE+A.COL1) 'TOTAL'
FROM (SELECT ID,SUM(COL1) 'COL1' FROM TB GROUP BY ID) A
LEFT JOIN TB1 B ON A.ID=B.AID AND YEAR(B.DATE) LIKE 2009
GROUP BY A.ID

呢?SYSCOLUMNS表里能取到这样的列吗?


这种需求本身是不符合常理的,连字段都不知道的去统计它基本上没啥意义
它统计出来的就是一个数字,这数字是怎么得来的,是否正确都无法验证

如果真要统计,可以把查询的结果插入到临时表里,这样也是对一个表进行判断和操作
[/Quote]
呵呵知道了,看来是我胡思乱想了。
当时的第一想法是用SELECT INTO生成#表,但#表的列类型不会获取,所以才有这个问题。
百年树人 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 guguda2008 的回复:]
引用 12 楼 josy 的回复:
既然这样,我就先来献个丑吧
SQL code--->测试数据ifobject_id('[tb]')isnotnulldroptable[tb]gocreatetable[tb]([col1]varchar(1),[col2]int,[col3]varchar(1),[col4] numeric(2,1))insert[tb]select'a',1,'b',3unionallselect'c',5,'d',3.5--->查询declare@sqlvarchar(8000)select@sql=isnull(@sql+',','')+'sum(['+a.name+']) as ['+a.name+']'from
  syscolumns a,systypes bwhere
  a.xtype=b.xtypeand
  a.id=object_id('tb')and
  b.namein('tinyint','smallint','decimal','int','real','money','float','bigint','numeric','smallmoney')orderby colidset@sql='select'+@sql+' from tb'exec(@sql)/**
col2        col4                                   
----------- ----------------------------------------
6          6.5
**/

树哥这个可以实现对单表的数字列合计查询,但是如果是这样的语句

SELECT A.ID,SUM(B.PRICE+A.COL1) 'TOTAL'
FROM (SELECT ID,SUM(COL1) 'COL1' FROM TB GROUP BY ID) A
LEFT JOIN TB1 B ON A.ID=B.AID AND YEAR(B.DATE) LIKE 2009
GROUP BY A.ID

呢?SYSCOLUMNS表里能取到这样的列吗?
[/Quote]

这种需求本身是不符合常理的,连字段都不知道的去统计它基本上没啥意义
它统计出来的就是一个数字,这数字是怎么得来的,是否正确都无法验证

如果真要统计,可以把查询的结果插入到临时表里,这样也是对一个表进行判断和操作
jimwoo 2009-08-29
  • 打赏
  • 举报
回复
先插入一个中间表
declare @s varchar(8000), @tabe char(10)

set @s = 'SELECT A.ID,SUM(B.PRICE+A.COL1) TOTAL into ' + @table +
'FROM (SELECT ID,SUM(COL1) COL1 FROM TB GROUP BY ID) A ' +
'LEFT JOIN TB1 B ON A.ID=B.AID AND YEAR(B.DATE) LIKE 2009 ' +
'GROUP BY A.ID '

exec(@s)
exec usp1 @table
guguda2008 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 fanzhouqi 的回复:]
字符行置为空 我实现不了SQL codedeclare@strvarchar(8000)set@str=''select@str=@str+','+a.name+'=case when'''+c.name+''' =''int'' then sum(isnull('+a.name+',0)) else''''end'from syscolumns ainnerjoin sysobjects ¡­
[/Quote]

[Quote=引用 16 楼 jimwoo 的回复:]
SQL code--数据表createtable tb(aint, bchar(10), cdecimal(18,3), dchar(10))insert tbselect1,'a',2,'b'unionallselect3,'c',4,'d'go--存储过程createprocedure usp1@tablevarchar(10)asdeclare@svarchar(8000)set@s=''s¡­
[/Quote]

谢谢大家的积极讨论!

看来大家都想到了用SYSCOLUMNS来查询字段的类型,但是如同这样的查询

SELECT A.ID,SUM(B.PRICE+A.COL1) 'TOTAL'
FROM (SELECT ID,SUM(COL1) 'COL1' FROM TB GROUP BY ID) A
LEFT JOIN TB1 B ON A.ID=B.AID AND YEAR(B.DATE) LIKE 2009
GROUP BY A.ID

这只是我随便写的一个SQL,SELECT后面的是各种复杂计算的结果,FROM后面的也不是直接从数据库中读出的表,这样就不能从SYSCOLUMNS里找到对应列的值了

我现在想到了用ISNUMERIC来判断SELECT后面的每一列然后用CASE WHEN来区分。
guguda2008 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 josy 的回复:]
既然这样,我就先来献个丑吧
SQL code--->测试数据ifobject_id('[tb]')isnotnulldroptable[tb]gocreatetable[tb]([col1]varchar(1),[col2]int,[col3]varchar(1),[col4] numeric(2,1))insert[tb]select'a',1,'b',3unionallselect'c',5,'d',3.5--->查询declare@sqlvarchar(8000)select@sql=isnull(@sql+',','')+'sum(['+a.name+']) as ['+a.name+']'from
syscolumns a,systypes bwhere
a.xtype=b.xtypeand
a.id=object_id('tb')and
b.namein('tinyint','smallint','decimal','int','real','money','float','bigint','numeric','smallmoney')orderby colidset@sql='select'+@sql+' from tb'exec(@sql)/**
col2 col4
----------- ----------------------------------------
6 6.5
**/
[/Quote]
树哥这个可以实现对单表的数字列合计查询,但是如果是这样的语句

SELECT A.ID,SUM(B.PRICE+A.COL1) 'TOTAL'
FROM (SELECT ID,SUM(COL1) 'COL1' FROM TB GROUP BY ID) A
LEFT JOIN TB1 B ON A.ID=B.AID AND YEAR(B.DATE) LIKE 2009
GROUP BY A.ID

呢?SYSCOLUMNS表里能取到这样的列吗?
jimwoo 2009-08-29
  • 打赏
  • 举报
回复
--数据表
create table tb(a int, b char(10), c decimal(18,3), d char(10))
insert tb
select 1, 'a', 2, 'b' union all
select 3, 'c', 4, 'd'
go

--存储过程
create procedure usp1 @table varchar(10) as
declare @s varchar(8000)

set @s = ''
select @s = @s + ',' + case when type in ('bigint', 'decimal', 'float', 'int', 'numeric', 'real', 'smallint', 'tinyint') then 'sum(' + name + ') as ' + name else 'null as ' + name end from
(
select top 100 percent a.name, b.name as type from syscolumns a join systypes b on a.xtype = b.xtype
where a.id = object_id(@table) order by a.colid
) t

set @s = 'select ' + substring(@s, 2, len(@s) - 1) + ' from ' + @table
exec(@s)
go

--执行
exec usp1 'tb'

drop table tb
drop procedure usp1
/*
a b c d
----------- ----------- ---------------------------------------- -----------
4 NULL 6.000 NULL
*/
htl258_Tony 2009-08-29
  • 打赏
  • 举报
回复
树哥真强,我还没看懂题意。
fanzhouqi 2009-08-29
  • 打赏
  • 举报
回复
字符行置为空 我实现不了

declare @str varchar(8000)
set @str = ''
select @str = @str+','+a.name+'=case when '''+c.name+''' = ''int'' then sum(isnull('+a.name+',0)) else ''''end' from syscolumns a
inner join sysobjects b on a.id = b.id
inner join systypes c on a.xusertype=c.xusertype
where b.name = 'tb' and c.name = 'int'
set @str = right(@str,len(@str)-1)
set @str = 'select '+@str+' from tb'



print (@str)
exec (@str)


select * from tb

ID Num PID
----------- ----------- -----------
45 4500 21

ID PID Num text
----------- ----------- ----------- ----------
1 NULL 100 222
2 1 200 333
3 2 300 444
4 3 400 555
5 1 500 666
6 NULL 600 777
7 NULL 700 888
8 7 800 999
9 7 900 111
华夏小卒 2009-08-29
  • 打赏
  • 举报
回复
树哥强
百年树人 2009-08-29
  • 打赏
  • 举报
回复
既然这样,我就先来献个丑吧
--->测试数据
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([col1] varchar(1),[col2] int,[col3] varchar(1),[col4] numeric(2,1))
insert [tb]
select 'a',1,'b',3 union all
select 'c',5,'d',3.5

--->查询
declare @sql varchar(8000)

select
@sql=isnull(@sql+',','')+'sum(['+a.name+']) as ['+a.name+']'
from
syscolumns a,systypes b
where
a.xtype=b.xtype
and
a.id=object_id('tb')
and
b.name in('tinyint','smallint','decimal','int','real','money','float','bigint','numeric','smallmoney')
order by colid

set @sql='select '+@sql+' from tb'

exec(@sql)

/**
col2 col4
----------- ----------------------------------------
6 6.5
**/
黄_瓜 2009-08-29
  • 打赏
  • 举报
回复
o
gw6328 2009-08-29
  • 打赏
  • 举报
回复
帮顶!
gw6328 2009-08-29
  • 打赏
  • 举报
回复
看不懂!
guguda2008 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 liangck 的回复:]
.....
[/Quote]
梁哥试试啊,谁先弄出来100分就是谁的
guguda2008 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 josy 的回复:]
这么技术的贴被你自己水了
[/Quote]
周末嘛,不水一下怎么对的起自己的人生,反正问题已经解决了就当作一个小挑战来练练脑子好了
--小F-- 2009-08-29
  • 打赏
  • 举报
回复
一同来学习
加载更多回复(7)

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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