一复杂存储过程写法!

求一复杂存储过程写法!

楼主suppanda007(小宝) 2006-08-28 17:44:07 在 MS-SQL Server / 基础类 提问

有一个表   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       未订                   未订  
  --*/

### 回答1: MySQL 存储过程写法如下所示: CREATE PROCEDURE procedure_name (IN param1 datatype1, IN param2 datatype2, ..., OUT result_name datatype) BEGIN -- 写入存储过程的处理逻辑 -- 可以使用 IF、CASE、LOOP、WHILE 等语句 -- 最后将结果存储到 result_name 中 END; 其中,procedure_name 为存储过程的名称,param1、param2 等为存储过程的输入参数,result_name 为存储过程的输出参数。在 BEGIN 和 END 之间编写存储过程的处理逻辑,最后将结果存储到输出参数中,以便后续使用。 ### 回答2: MySQL存储过程是一组预先编译好的SQL语句。它们被存储在数据库中,并可以通过调用来执行。MySQL存储过程写法如下: 1. 创建存储过程: 使用 `CREATE PROCEDURE` 语句创建存储过程。例如,如果要创建一个名为 `myprocedure` 的存储过程,可以使用以下语法: ``` CREATE PROCEDURE myprocedure() BEGIN -- 写入存储过程的SQL语句 -- ... END; ``` 2. 存储过程参数: 存储过程可以接受输入参数和输出参数,以便传递数据。以下是定义存储过程参数的语法: ``` CREATE PROCEDURE myprocedure(IN input_param INT, OUT output_param INT) BEGIN -- 使用 input_param 和 output_param 进行操作 -- ... END; ``` 在存储过程中使用 `IN` 关键字定义输入参数,并使用 `OUT` 关键字定义输出参数。 3. 存储过程内容: 在 `BEGIN` 和 `END` 关键字之间,可以编写一系列SQL语句来定义存储过程的功能。这些语句可以包含条件、循环、查询和其他SQL操作。 例如,以下存储过程通过将两个参数相加,并将结果存储到输出参数中: ``` CREATE PROCEDURE myprocedure(IN a INT, IN b INT, OUT result INT) BEGIN SET result = a + b; END; ``` 4. 调用存储过程: 要调用存储过程,可以使用 `CALL` 语句,后跟存储过程的名称和参数列表。例如,调用上面创建的存储过程可以使用以下语法: ``` CALL myprocedure(3, 4, @output); ``` 在这个例子中,存储过程的输入参数分别为3和4,结果存储在 `@output` 变量中。 以上是MySQL存储过程的一般写法存储过程为我们提供了一种方便的方式来存储和执行复杂的数据库操作,提高了数据库的可维护性和可重用性。 ### 回答3: MySQL存储过程是一组预先编译的SQL语句,通过调用存储过程来执行这些SQL语句。MySQL存储过程具有以下写法: 1. 创建存储过程: 使用CREATE PROCEDURE语句创建存储过程,语法如下: CREATE PROCEDURE procedure_name ([parameter_list]) [characteristics] stored_procedure_body 其中,procedure_name是存储过程的名称,parameter_list是存储过程的参数列表,characteristics是字符集、安全性等特性,stored_procedure_body是存储过程的具体实现代码。 2. 删除存储过程: 使用DROP PROCEDURE语句删除存储过程,语法如下: DROP PROCEDURE [IF EXISTS] procedure_name 其中,procedure_name是要删除的存储过程的名称。IF EXISTS是可选的,表示当存储过程不存在时不会产生错误。 3. 编辑存储过程: 使用ALTER PROCEDURE语句编辑存储过程,语法如下: ALTER PROCEDURE procedure_name ([parameter_list]) [characteristics] stored_procedure_body 其中,procedure_name是要编辑的存储过程的名称,parameter_list是存储过程的参数列表,characteristics是字符集、安全性等特性,stored_procedure_body是存储过程的新实现代码。 4. 执行存储过程: 使用CALL语句执行存储过程,语法如下: CALL procedure_name([parameters]) 其中,procedure_name是要执行的存储过程的名称,parameters是存储过程的参数列表。 总结来说,MySQL存储过程写法包括创建、删除、编辑和执行四个步骤。创建存储过程使用CREATE PROCEDURE语句,删除存储过程使用DROP PROCEDURE语句,编辑存储过程使用ALTER PROCEDURE语句,执行存储过程使用CALL语句。同时,存储过程可以带有参数,通过参数列表进行传递。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值