求一复杂存储过程写法!
有一个表 Table A 结构如下
姓名 颜色1 颜色2 评语
name color1 color2 commint
a 1 -1 好
b 2 1 不好
a 3 2 一般
c 2 1 ss
a -1 2 aa
b 4 -1 bb
a 2 -1 cc
按照如下规则进行统计:
按姓名分组求平均值,如果值为-1就不统计,评语累计
统计后结果如下:
name color1 color2 commint
a 2 2 好,一般,aa,cc
b 3 1 不好,bb
c 2 1 ss 问题点数:100、回复次数:7Top
1 楼libin_ftsafe(子陌红尘(TS for Banking Card))回复于 2006-08-28 17:47:08 得分 10
函数,参考这个:
--生成测试数据
create table 表(部门 int,人员 varchar(20))
insert into 表 select 1,'张三'
insert into 表 select 1,'李四'
insert into 表 select 1,'王五'
insert into 表 select 2,'赵六'
insert into 表 select 2,'邓七'
insert into 表 select 2,'刘八'
go
--创建用户定义函数
create function f_str(@department int)
returns varchar(8000)
as
begin
declare @ret varchar(8000)
set @ret = ''
select @ret = @ret+','+人员 from 表 where 部门 = @department
set @ret = stuff(@ret,1,1,'')
return @ret
end
go
--执行
select 部门,人员=dbo.f_str(部门) from 表 group by 部门 order by 部门
go
--输出结果
/*
部门 人员
---- --------------
1 张三,李四,王五
2 赵六,邓七,刘八
*/
--删除测试数据
drop function f_str
drop table 表
goTop
2 楼WangZWang(先来)回复于 2006-08-28 17:49:07 得分 10
--合並函數
create FUNCTION uf_HB(@name varchar(50))
RETURNS varchar(8000)
AS
BEGIN
DECLARE @r varchar(8000)
SET @r=''
SELECT @r=@r+','+rtrim(commint)
FROM 表 WHERE name=@name
RETURN(stuff(@r,1,1,''))
END
go
SELECT name,color1=sum(color1),color2=sum(color2),[commint]=dbo.uf_HB(name)
FROM 表
GROUP BY name
go
Top
3 楼libin_ftsafe(子陌红尘(TS for Banking Card))回复于 2006-08-28 17:54:44 得分 20
create function f_str(@name varchar(10))
returns varchar(20)
as
begin
declare @str varchar(20)
set @str=''
select @str=@str+','+commint from A where name=@name
set @str=stuff(@str,1,1,'')
return @str
end
go
select
t.name
color1/(case num1 when 0 then 1 else num1 end),
color2/(case num2 when 0 then 1 else num2 end),
t.commint
from
(select
name,
sum(case when color1!=-1 then color1 else 0 end) as color1,
sum(case when color1!=-1 then 1 else 0 end) as num1,
sum(case when color2!=-1 then color2 else 0 end) as color2,
sum(case when color2!=-1 then 1 else 0 end) as num2,
dbo.f_str(@name) as commint
from
A
group by
name) t
order by
t.nameTop
4 楼YiZhiNet(九斤半)回复于 2006-08-28 17:58:56 得分 10
create table A(name char(1),color1 int,color2 int,commint varchar(20))
insert A
select 'a',1,-1,'好' union all
select 'b',2,1,'不好' union all
select 'a',3,2,'一般' union all
select 'c',2,1,'ss' union all
select 'a',-1,2,'aa' union all
select 'b',4,-1,'bb' union all
select 'a',2,-1,'cc'
select * from A
go
create function F_Str(@name char(1))
returns varchar(250)
as
begin
declare @sql varchar(1000)
set @sql=''
select @sql=@sql+','+commint from a where [name]=@name
--STUFF ( character_expression1 , start , length ,character_expression2).
--字符串char1从start开始的第length位字符用char2字符串代替
return stuff(@sql,1,1,'')
end
go
select
name,
avg(case color1 when -1 then null else color1 end) as color1,
avg(case color2 when -1 then null else color2 end) as color1,
dbo.F_Str(name)
from A
group by name
drop function F_Str
drop table ATop
5 楼suppanda007(小宝)回复于 2006-08-29 09:34:38 得分 0
我用的是db2数据库
只用了libin_ftsafe(子陌红尘:当libin告别ftsafe)的这段代码就解决了
select
t.name,
t.id,
color/(case num1 when 0 then 1 else num1 end) as color,
color1/(case num2 when 0 then 1 else num2 end) as color1
from
(select
name,
id,
sum(case when color!=-1 then color else 0 end) as color,
sum(case when color!=-1 then 1 else 0 end) as num1,
sum(case when color1!=-1 then color1 else 0 end) as color1,
sum(case when color1!=-1 then 1 else 0 end) as num2
from
wy_stat_test
group by
name,id
order by
name
) as t
多谢大家了!
还有一个疑问,用f_str和t.commit有什么用呢!Top
6 楼libin_ftsafe(子陌红尘(TS for Banking Card))回复于 2006-08-29 10:55:51 得分 50
f_str是一个用户定义函数,非标准函数;t.commit是为f_str函数返回结果取的别名。Top
7 楼suppanda007(小宝)回复于 2006-08-29 11:35:51 得分 0
还有一个问题当我把这些数据插入到表里面,出现错误:
insert into result values(
select
t.name,
t.id,
color/(case num1 when 0 then 1 else num1 end) as color,
color1/(case num2 when 0 then 1 else num2 end) as color1
from
(select
name,
id,
sum(case when color!=-1 then color else 0 end) as color,
sum(case when color!=-1 then 1 else 0 end) as num1,
sum(case when color1!=-1 then color1 else 0 end) as color1,
sum(case when color1!=-1 then 1 else 0 end) as num2
from
wy_stat_test
group by
name,id
order by
name
) as t
);
错误提示:
从仅允许一列的子查询中返回了多列,SQLSTATE=42823,请问这是什么错误呢?
有表a(qid,tagname,rid,starttime,endtime,startweekday,endweekday,startdate,enddate)
各字段的含义 qid(楼层号)rid(房间编号),tagname(房间的状态),starttime(开始时间)endtime(结束时 间),startweekday(开始星期),endweekday(结束星期),startdate(开始日期),enddate(结束日期),d(为 优先级2比1高)
表内容如下:
qid j rid tagname starttime endtime startweekday endweekday startdate enddate d
1 1 A1 未订 8:00 9:00 1 5 null null 1
1 2 A1 未订 9:00 10:00 1 5 null null 1
1 3 A1 未订 10:00 11:00 1 5 null null 1
1 4 A1 装修 8:00 9:00 null null 2005-1-18 2005-1-19 2
1 5 A1 装修 9:00 10:00 null null 2005-1-18 2005-1-19 2
1 6 A1 装修 10:00 11:00 null null 2005-1-18 2005-1-19 2
1 7 A2 未订 8:00 9:00 1 5 null null 1
1 8 A2 未订 9:00 10:00 1 5 null null 1
1 9 A2 未订 10:00 11:00 1 5 null null 1
1 10 A2 装修 8:00 9:00 null null 2005-1-18 2005-1-19 2
1 11 A2 装修 9:00 10:00 null null 2005-1-18 2005-1-19 2
1 12 A2 装修 10:00 11:00 null null 2005-1-18 2005-1-19 2
startweekday ,endweekday代表平常周一到周五时各房间在不同时段的状态。startdate,enddate代表特殊日期各房间各时段的状态。要形成如下的 报表存储过程改如何写(传入的参数为日期如2005-1-17号,为星期一应该显示常规的周一到周五的状态,如果传入的为2005-1-18虽然为星期 二,但我们已特殊日期的优先级高,显示特殊日期时的设置)现在我们传入2005-1-17要显示成如下报表:
A1 A2
08:00-09:00 未订 未订
09:00-10:00 未订 未订
11:00-12:00 未订 未订
传入2005-1-18时显示如下
08:00-09:00 装修 装修
09:00-10:00 装修 装修
11:00-12:00 装修 装修
应用邹建的方法:
create proc p_qry
@date smalldatetime --要查询的日期
as
set nocount on
declare @week int,@s nvarchar(4000)
--格式化日期和得到星期
select @date=convert(char(10),@date,120)
,@week=(@@datefirst+datepart(weekday,@date)-1)%7
,@s=''
select id=identity(int),* into #t
from(
select top 100 percent
qid,rid,tagname,
starttime=convert(char(5),starttime,108),
endtime=convert(char(5),endtime,108)
from tb
where (@week between startweekday and endweekday)
or(@date between startdate and enddate)
order by qid,rid,starttime,d desc)a
select @s=@s+N',['+rtrim(rid)
+N']=max(case when qid='+rtrim(qid)
+N' and rid=N'''+rtrim(rid)
+N''' then tagname else N'''' end)'
from #t group by qid,rid
exec('
select starttime,endtime'+@s+'
from #t a
where not exists(
select * from #t
where qid=a.qid and rid=a.rid
and starttime=a.starttime
and endtime=a.endtime
and id<a.id)
group by starttime,endtime')
已经达到我要的目的了。但我还有一张表c是记录预定信息的表如下:
id qid rid consumedate j
1 1 A1 2005-1-17 1
1 1 A2 2005-1-17 2
(qid属于那楼、rid哪个房间、consumedate 订的是哪个一天的,j(与a表的j)标识是订的是那个时段的
a表为为初使设置房间的在不同时间的状态。如我要输入日期2005-1-17号显示如下
A1 A2
08:00-09:00 被订 未订
09:00-10:00 未订 被订
11:00-12:00 未订 未订
该如何写这样的存储过程呢? 问题点数:50、回复次数:2Top
1 楼waiking33(waiking_wei)回复于 2005-01-20 17:19:40 得分 0
高手都跑到哪里去了,自己顶一下Top
2 楼zjcxc(邹建)回复于 2005-01-21 10:05:35 得分 50
--示例数据
create table a(
qid int,j int,rid nvarchar(10),tagname nvarchar(10),
starttime smalldatetime,endtime smalldatetime,
startweekday int,endweekday int,
startdate smalldatetime,enddate smalldatetime,d int)
insert a select 1,1 ,'A1','未订','08:00','09:00',1 ,5 ,null ,null ,1
union all select 1,2 ,'A1','未订','09:00','10:00',1 ,5 ,null ,null ,1
union all select 1,3 ,'A1','未订','10:00','11:00',1 ,5 ,null ,null ,1
union all select 1,4 ,'A1','装修','08:00','09:00',null,null,'2005-1-18','2005-1-19',2
union all select 1,5 ,'A1','装修','09:00','10:00',null,null,'2005-1-18','2005-1-19',2
union all select 1,6 ,'A1','装修','10:00','11:00',null,null,'2005-1-18','2005-1-19',2
union all select 1,7 ,'A2','未订','08:00','09:00',1 ,5 ,null ,null ,1
union all select 1,8 ,'A2','未订','09:00','10:00',1 ,5 ,null ,null ,1
union all select 1,9 ,'A2','未订','10:00','11:00',1 ,5 ,null ,null ,1
union all select 1,10,'A2','装修','08:00','09:00',null,null,'2005-1-18','2005-1-19',2
union all select 1,11,'A2','装修','09:00','10:00',null,null,'2005-1-18','2005-1-19',2
union all select 1,12,'A2','装修','10:00','11:00',null,null,'2005-1-18','2005-1-19',2
create table c(id int,qid int,rid varchar(10),consumedate smalldatetime,j int)
insert c select 1,1,'A1','2005-1-17',1
union all select 1,1,'A2','2005-1-17',8
go
create proc p_qry
@date smalldatetime --要查询的日期
as
set nocount on
declare @week int,@s nvarchar(4000)
--格式化日期和得到星期
select @date=convert(char(10),@date,120)
,@week=(@@datefirst+datepart(weekday,@date)-1)%7
,@s=''
select id=identity(int),* into #t
from(
select top 100 percent
a.qid,a.rid,a.j,
tagname=case when c.id is null then a.tagname else N'被订' end,
starttime=convert(char(5),a.starttime,108),
endtime=convert(char(5),a.endtime,108)
from a
left join c on a.qid=c.qid and a.rid=c.rid and a.j=c.j
and c.consumedate=@date
where (@week between a.startweekday and a.endweekday)
or(@date between a.startdate and a.enddate)
order by a.qid,a.rid,a.starttime,a.d desc)a
select @s=@s+N',['+rtrim(rid)
+N']=max(case when qid='+rtrim(qid)
+N' and rid=N'''+rtrim(rid)
+N''' then tagname else N'''' end)'
from #t group by qid,rid
exec('
select starttime,endtime'+@s+'
from #t a
where not exists(
select * from #t
where qid=a.qid and rid=a.rid
and starttime=a.starttime
and endtime=a.endtime
and id<a.id)
group by starttime,endtime')
go
--调用
exec p_qry '2005-1-17'
go
--删除测试
drop table a,c
drop proc p_qry
/*&/--测试结果
starttime endtime A1 A2
--------- ------- ---------- ----------
08:00 09:00 被订 未订
09:00 10:00 未订 被订
10:00 11:00 未订 未订
--*/