存储过程的典型例子

普通行列转换

假设有张学生成绩表(t)如下

Name Subject Result
张三 语文  73
张三 数学  83
张三 物理  93
李四 语文  74
李四 数学  84
李四 物理  94

想变成
姓名 语文 数学 物理
张三 73  83  93
李四 74  84  94

create table #t
(
   Name    varchar(10) ,
   Subject varchar(10) ,
   Result  int
)

insert into #t(Name , Subject , Result) values('张三','语文','73')
insert into #t(Name , Subject , Result) values('张三','数学','83')
insert into #t(Name , Subject , Result) values('张三','物理','93')
insert into #t(Name , Subject , Result) values('李四','语文','74')
insert into #t(Name , Subject , Result) values('李四','数学','83')
insert into #t(Name , Subject , Result) values('李四','物理','93')

declare @sql varchar(8000)
set @sql = 'select Name as ' + '姓名'
select @sql = @sql + ' , sum(case Subject when ''' + Subject + ''' then Result end) [' + Subject + ']'
from (select distinct Subject from #t) as a
set @sql = @sql + ' from #t group by name'
exec(@sql)

drop table #t

--结果
姓名       数学        物理        语文         
---------- ----------- ----------- -----------
李四       83          93          74
张三       83          93          73
 
----------------------------------------------------
如果上述两表互相换一下:即

姓名 语文 数学 物理
张三 73  83  93
李四 74  84  94

想变成
Name Subject Result
张三 语文  73
张三 数学  83
张三 物理  93
李四 语文  74
李四 数学  84
李四 物理  94

create table #t
(
   姓名 varchar(10) ,
   语文 int ,
   数学 int ,
   物理 int
)

insert into #t(姓名 , 语文 , 数学 , 物理) values('张三',73,83,93)
insert into #t(姓名 , 语文 , 数学 , 物理) values('李四',74,84,94)

select 姓名 as Name,'语文' as Subject,语文 as Result from #t union
select 姓名 as Name,'数学' as Subject,数学 as Result from #t union
select 姓名 as Name,'物理' as Subject,物理 as Result from #t
order by 姓名 desc

drop table #t
 
--结果
Name       Subject Result     
---------- ------- -----------
张三       数学    83
张三       物理    93
张三       语文    73
李四       数学    84
李四       物理    94
李四       语文    74

(所影响的行数为 6 行)

 

--带符号合并行列转换

--有表t,其数据如下:
  a b
  1 1
  1 2
  1 3
  2 1
  2 2
  3 1
--如何转换成如下结果:
  a b
  1 1,2,3
  2 1,2
  3 1

create table tb
(
   a int,
   b int
)
insert into tb(a,b) values(1,1)
insert into tb(a,b) values(1,2)
insert into tb(a,b) values(1,3)
insert into tb(a,b) values(2,1)
insert into tb(a,b) values(2,2)
insert into tb(a,b) values(3,1)
go

if object_id('pubs..f_hb') is not null
   drop function f_hb
go

--创建一个合并的函数
create function f_hb(@a int)
returns varchar(8000)
as
begin
  declare @str varchar(8000)
  set @str = ''
  select @str = @str + ',' + cast(b as varchar) from tb where a = @a
  set @str = right(@str , len(@str) - 1)
  return(@str)
End
go

--调用自定义函数得到结果:
select distinct a ,dbo.f_hb(a) as b from tb

drop table tb

--结果
a           b    
----------- ------
1           1,2,3
2           1,2
3           1

(所影响的行数为 3 行)


多个前列的合并
数据的原始状态如下:
ID  PR   CON  OP    SC
001 p    c    差    6
001 p    c    好    2
001 p    c    一般  4
002 w    e    差    8
002 w    e    好    7
002 w    e    一般  1
===========================
用SQL语句实现,变成如下的数据
ID  PR   CON  OPS
001 p    c    差(6),好(2),一般(4)
002 w    e    差(8),好(7),一般(1)

if object_id('pubs..tb') is not null
   drop table tb
go

create table tb
(
id varchar(10),
pr varchar(10),
con varchar(10),
op varchar(10),
sc int
)
 
insert into tb(ID,PR,CON,OP,SC) values('001', 'p',    'c',    '差',    6)
insert into tb(ID,PR,CON,OP,SC) values('001', 'p',    'c',    '好',    2)
insert into tb(ID,PR,CON,OP,SC) values('001', 'p',    'c',    '一般',  4)
insert into tb(ID,PR,CON,OP,SC) values('002', 'w',    'e',    '差',    8)
insert into tb(ID,PR,CON,OP,SC) values('002', 'w',    'e',    '好',    7)
insert into tb(ID,PR,CON,OP,SC) values('002', 'w',    'e',    '一般',  1)
go

if object_id('pubs..test') is not null
   drop table test
go
select ID,PR,CON , OPS = op + '(' + cast(sc as varchar(10)) + ')' into test from tb

--创建一个合并的函数
if object_id('pubs..f_hb') is not null
   drop function f_hb
go
create function f_hb(@id varchar(10),@pr varchar(10),@con varchar(10))
returns varchar(8000)
as
begin
  declare @str varchar(8000)
  set @str = ''
  select @str = @str + ',' + cast(OPS as varchar) from test where id = @id and @pr = pr and @con = con
  set @str = right(@str , len(@str) - 1)
  return(@str)
End
go

--调用自定义函数得到结果:
select distinct id ,pr , con , dbo.f_hb(id,pr,con) as OPS from test

drop table tb
drop table test

--结果
id         pr         con        OPS               
---------- ---------- ---------- -------------------
001        p          c          差(6),好(2),一般(4)
002        w          e          差(8),好(7),一般(1)

(所影响的行数为 2 行)

 

create table b
(col varchar(20))

insert b values ('a')
insert b values ('b')
insert b values ('c')
insert b values ('d')
insert b values ('e')


declare @sql varchar(1024)
set @sql=''
select @sql=@sql+b.col+',' from (select col from b) as b
set @sql='select '''+@sql+''''
exec(@sql)

 

行列转换并取平均值

站名 年份   数据
AA    1986  23.5
AA    1987  25.6
AA    1988  23.0
BB    1986  21.0
BB    1987  22.0
BB    1988  22.7
CC    1986  21.8
CC    1987  23.0
CC    1988  21.8
......

我想写成这样的表:
 序号   年份      AA       BB      CC      ....平均
 1      1986      23.5     21.0    21.8    ....22.1   
 2      1987      25.6     22.0    23.0    ....23.5
 3      1988      23.0     22.7    21.8    ....22.5


create table #tab ([站名][char](10),[年份] [int],[数据] [decimal](18, 1))
insert #tab values('AA',1986,23.5)
insert #tab values('AA',1987,25.6)
insert #tab values('AA',1988,23.0)
insert #tab values('BB',1986,21.0)
insert #tab values('BB',1987,22.0)
insert #tab values('BB',1988,22.7)
insert #tab values('CC',1986,21.8)
insert #tab values('CC',1987,23.0)
insert #tab values('CC',1988,21.8)

declare @sql varchar(4000)
set @sql = 'select 年份 '
select @sql = @sql + ' , sum(case 站名 when '''+ 站名 +''' then 数据 end) ['+ 站名 +']'
from (select distinct 站名 from #tab) as a
set @sql = @sql + ', avg(数据) as 平均 from #tab group by 年份'
exec(@sql)

drop table #tab

年份 AA    BB    CC    平均                                      
---- ----- ----- ----- ----------
1986 23.5  21.0  21.8  22.100000
1987 25.6  22.0  23.0  23.533333
1988 23.0  22.7  21.8  22.500000


--另外的做法
declare @sql varchar(8000)
set @sql='select 年份'
select @sql=@sql+',['+站名+']=max(case 站名 when '''+站名+''' then 数据 end)' from 表 group by 站名 order by 站名
set @sql=@sql+',avg(数据) as 平均 from 表 group by 年份'
exec(@sql)

declare @name varchar(1000)
set @name=''
select @name=@name+',max(case when 站名='''+站名+''' then 數據 end) ['+站名+']' from test group by 站名 order by 站名
select @name='select identity(int,1,1)序號,年份'+@name+',cast(avg (數據) as decimal(15,1)) 平均 into #a from test group by 年份 order by 1 select * from #a'
exec (@name)
/*
序號年份AABBCC平均
1198623.521.021.822.1
2198725.622.023.023.5
3198823.022.721.822.5
*/

現有用SQL查詢出的數據如下,請問如何寫SQL才能得到轉換後的結果呢
DValue
C10
C21
C320.00
C110
C211
C312


轉換後

C1C2C3
0120
101112

--創建測試環境
Create Table 表
(ID Varchar(10),
Value Int)
--插入數據
Insert 表 Select 'C1',0
Union All Select 'C2',1
Union All Select 'C3',20
Union All Select 'C1',10
Union All Select 'C2',11
Union All Select 'C3',12
GO
--測試
--借用臨時表
Select ID2 = Identity(Int, 1, 1), * Into #T From 表

--如果ID是固定三個
Select
Max(Case ID When 'C1' Then Value Else 0 End) As C1,
Max(Case ID When 'C2' Then Value Else 0 End) As C2,
Max(Case ID When 'C3' Then Value Else 0 End) As C3
From
(Select OrderID = (Select Count(ID2) From #T Where ID = A.ID And ID2 <= A.ID2), * From #T A) B
Group By
OrderID

--如果ID不是固定三個
Declare @S Varchar(8000)
Select @S = ''
Select @S = @S + ', Max(Case ID When ''' + ID + ''' Then Value Else 0 End) As [' + ID + ']'
From 表 Group By ID
Select @S= 'Select ' + Stuff(@S, 1, 1, '') + ' From (Select OrderID = (Select Count(ID2) From #T Where ID = A.ID And ID2 <= A.ID2), * From #T A) B Group By OrderID '
EXEC(@S)

Drop Table #T
GO
--刪除測試環境
Drop Table 表
--結果
/*
C1C2C3
0120
101112
*/

 

 

表 department
departmenid(部门ID) parentid(父部门ID)
1 0
2 1
3 1
4 2
5 2
6 3
7 3
8 7

我查询部门ID ,张三对应的部门ID为8 ,如何查出张三的所有部门ID(包括父部门ID),如8,7,3,1

--建立測試環境
Create Table department
(departmenid Int,
parentid Int)
Insert department Select 60, null
Union All Select 1, 0
Union All Select 2, 1
Union All Select 3, 1
Union All Select 4, 2
Union All Select 5, 2
Union All Select 6, 3
Union All Select 7, 3
Union All Select 8, 7
GO
--建立函數
Create Function F_GetParent(@departmenid Int)
Returns @Tree Table (departmenid Int, parentid Int)
As
Begin
Insert @Tree Select * From department Where departmenid = @departmenid
While @@Rowcount > 0
Insert @Tree Select A.* From department A Inner Join @Tree B On A.departmenid = B.parentid And A.departmenid Not In (Select departmenid From @Tree) Where A.parentid Is Not Null
Return
End
GO
--測試
Select departmenid From dbo.F_GetParent(8) Order By parentid
GO
--刪除測試環境
Drop Table department
Drop Function F_GetParent
--結果
/*
departmenid
1
3
7
8
*/

我写的一种方法:
Create Function F_GetParent(@departmenid Int)
Returns @Tree Table (departmenid Int, parentid Int)
As
Begin
declare @i varchar(100)
While @departmenid <>0
begin
select  @i=parentid From department Where departmenid = @departmenid
Insert @Tree Select * From department Where departmenid = @departmenid
set @departmenid =@i
end
Return
End

 

--創建存儲過程
Create ProceDure SP_GetParent(@departmenid Int)
As
Begin
Select * Into #Tree From department Where departmenid = @departmenid
While @@Rowcount > 0
Insert #Tree Select A.* From department A Inner Join #Tree B On A.departmenid = B.parentid And A.departmenid Not In (Select departmenid From #Tree) Where A.parentid Is Not Null
Select departmenid From #Tree Order By parentid
Drop Table #Tree
End
GO
--測試
EXEC SP_GetParent 8
GO
--刪除測試環境
Drop Table department
Drop ProceDure SP_GetParent
--結果
/*
departmenid
1
3
7
8
*/


这里有一个递归的列子:
create table ta (项目 varchar(20),上级项目 varchar(20),num int)
insert ta
select  'A ', ' ' ,100 union all
select  'B ', 'A ' ,200 union all
select  'C ', 'B ' ,300 union all
select  'D ', 'B ' ,400 union all
select  'E ', 'C ' ,500 union all
select  'F ', 'D ' ,600 union all
select  'H ', 'E ' ,700 union all
select  'G ', 'F ' ,800 

如果要显示上级的项目:


create function roy_f(@项目 varchar(20))
returns varchar(100)
as
begin

declare @上级项目 varchar(20)

select @上级项目=上级项目 from ta where 项目=@项目

return case when @上级项目 is null then null 

            else  isnull(dbo.roy_f(@上级项目)+ '- ', ' ')+@项目 end
end


go
select 项目,关系=dbo.roy_f(项目) from ta


id num
01 0
01 1
01 -1

希望得到如下结果
id n1 n2 n3
01 0 1 -1

create table #a (id varchar(10),num int)

insert into #a
select '01',-4
union all select '01',0
union all select '01',61
union all select '02',-5
union all select '02',16
union all select '02',8

select * from #a
drop table #a



Select ID2 = Identity(Int, 1, 1), * Into #T From #a

--1
declare @sql varchar(1000)
set @sql='select id'
select @sql=@sql+',max(case when OrderID='''+ cast(OrderID as varchar(10))+'''then num end )as num'+cast(OrderID as varchar(10)) from (select distinct  OrderID from  (Select OrderID = (Select Count(ID2) From #T Where ID = A.ID And ID2 <= A.ID2), * From #T A)b)c
select @sql=@sql+' from (Select OrderID = (Select Count(ID2) From #T Where ID = A.ID And ID2 <= A.ID2), * From #T A)b group by id'
print @sql
exec(@sql)

--2
declare @T int,@Max int,@sql varchar(1000)
select top 1 @Max=count(1),@T=1 from #t group by id order by count(1) desc
set @sql=''
while (@T<=@Max)
begin
select @sql=@sql+',[n'+cast(@T as varchar(100))+']=max(case OrderID when '''+cast(@T as varchar(100))+''' then num end)'
set @T=@T+1
end
select @sql='select id'+@sql+' from (Select OrderID = (Select Count(ID2) From #T Where ID = A.ID And ID2 <= A.ID2), * From #T A)b group by id'
print @sql
exec(@sql)



mysql存储过程用法

DELIMITER $$

DROP PROCEDURE IF EXISTS `test`.`proc_sms2`$$

CREATE PROCEDURE proc_sms2
(
in qudao varchar(100) ,
in ruleid varchar(100) 
)
BEGIN
DROP TABLE IF EXISTS NEWTT;
select qudao;
SET @SQL1='';
select @SQL1:= CONCAT(@SQL1,' , sum(case rulefield when ''' , rulefield , '''
then fieldvalue end) AS `' , rulefield , '`')
from (select distinct rulefield from sms) as a;
SET @v_sql = CONCAT('CREATE TABLE NEWTT AS select max(qudao) as 渠道, max(ruleid) as 策略 ',@sql1 , ',max(operate) as 操作, max(priority) as 优先级 ,flag from sms where qudao=/'',qudao,'/' group by flag');
PREPARE stmt2 FROM @v_sql;
EXECUTE stmt2;

END$$

DELIMITER ;
 
call proc_sms2("kjava","rule1")

select * from NEWTT

 


---------------------------------触发器

create trigger tri_users_insert
on users instead of insert
as
begin
insert users select i.name,i.companyId,c.companyName
from inserted i,company c
where i.companyId = c.companyId
end

create trigger tri_users_insert
on users after insert
as
begin
update u set u.companyName = c.companyName
from users u,inserted i,company c
where i.companyId = c.companyId and i.companyId = u.companyId
end

SQL code
      
      

IF OBJECT_ID ( ' A ' ) IS NOT NULL
DROP TABLE A
IF OBJECT_ID ( ' B ' ) IS NOT NULL
DROP TABLE B
IF OBJECT_ID ( ' c ' ) IS NOT NULL
DROP TABLE c

GO

CREATE TABLE A( id int ,坐标x DECIMAL ( 19 , 5 ),w_id int )
go
insert A SELECT
01 , 39.72555 , 01 UNION ALL SELECT
02 , 39.58586 , 02


CREATE TABLE B( id int ,坐标x DECIMAL ( 19 , 5 ),巡检时间 datetime )
go
insert B SELECT
01 , 39.12 , ' 2009-8-1 ' UNION ALL SELECT
02 , 39.78586 , ' 2009-8-3 ' UNION ALL SELECT
02 , 39.53586 , ' 2009-8-1 ' UNION ALL SELECT
02 , 39.483246 , ' 2009-8-22 ' UNION ALL SELECT
02 , 39.348586 , ' 2009-8-22 '


CREATE TABLE c( id int ,开始时间 datetime ,结束时间 datetime )
go
insert c SELECT
01 , ' 2009-8-1 ' , ' 2009-8-3 ' UNION ALL SELECT
02 , ' 2009-8-20 ' , ' 2009-8-23 '

go
if object_id ( ' gg ' ) is not null drop trigger gg
go
create trigger gg on a
for delete

as
if not exists ( select * from inserted) and exists ( select * from deleted)
begin
delete b from deleted de where de.id = b.id
delete c from deleted de where de.id = c.id
end
go
select * from b
select * from c -- 原始表

delete a where id = 02

select * from b -- 触发后表
select * from c

id 坐标x 巡检时间
-- --------- --------------------------------------- -----------------------
1 39.12000 2009 - 08 - 01 00 : 00 : 00.000
2 39.78586 2009 - 08 - 03 00 : 00 : 00.000
2 39.53586 2009 - 08 - 01 00 : 00 : 00.000
2 39.48325 2009 - 08 - 22 00 : 00 : 00.000
2 39.34859 2009 - 08 - 22 00 : 00 : 00.000

(
5 行受影响)

id 开始时间 结束时间
-- --------- ----------------------- -----------------------
1 2009 - 08 - 01 00 : 00 : 00.000 2009 - 08 - 03 00 : 00 : 00.000
2 2009 - 08 - 20 00 : 00 : 00.000 2009 - 08 - 23 00 : 00 : 00.000

(
2 行受影响)

(
4 行受影响)

(
1 行受影响)


(
1 行受影响)
id 坐标x 巡检时间
-- --------- --------------------------------------- -----------------------
1 39.12000 2009 - 08 - 01 00 : 00 : 00.000

(
1 行受影响)

id 开始时间 结束时间
-- --------- ----------------------- -----------------------
1 2009 - 08 - 01 00 : 00 : 00.000 2009 - 08 - 03 00 : 00 : 00.000


---------------------------------------游标
drop table tb
CREATE TABLE tb(col1 varchar(10),col2 int)
INSERT tb SELECT 'a',1
UNION ALL SELECT 'a',2
UNION ALL SELECT 'b',1
UNION ALL SELECT 'b',2
UNION ALL SELECT 'b',3


--合并处理
--定义结果集表变量
DECLARE @t TABLE(col1 varchar(10),col2 varchar(100))

--定义游标并进行合并处理
DECLARE tb CURSOR LOCAL
FOR
SELECT col1,col2 FROM tb ORDER BY  col1,col2
DECLARE @col1_old varchar(10),@col1 varchar(10),@col2 int,@s varchar(100)
OPEN tb
FETCH tb INTO @col1,@col2     <====>FETCH next from tb INTO @col1,@col2
print @col1
print @col2
SELECT @col1_old=@col1,@s=''
WHILE @@FETCH_STATUS=0
BEGIN
    IF @col1=@col1_old
        SELECT @s=@s+','+CAST(@col2 as varchar)
    ELSE
    BEGIN
        INSERT @t VALUES(@col1_old,STUFF(@s,1,1,''))
        SELECT @s=','+CAST(@col2 as varchar),@col1_old=@col1
    END
    FETCH tb INTO @col1,@col2
END
INSERT @t VALUES(@col1_old,STUFF(@s,1,1,''))
CLOSE tb
DEALLOCATE tb
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值