to 7楼这个票号一般都是有为数规定的,前面可能有字轨如AB0000001,我只是把前面的字母没有放上来!
学习 SQL 很深啊!!!
小梁,苦行僧,dobear,快帮忙啊!还有其他高手,想想吧,这个sql应该很难吧!!
table1 序号 类别 起始号 终止号 总数 已用票号 已用票数 结余票号 结余票数 组合编号(主键) 1 A 0000001 0000005 5 0000001,0000003 2 0000002,0000004,0000005 3 A-0000001-0000005 2 B 0000006 00000010 5 0000006,0000008 2 0000007,0000009,0000010 3 B-0000006-0000010 table2 组合编号 类别 票号 A-0000001-0000005 A 0000001 A-0000001-0000005 A 0000003 B-0000006-0000010 B 0000006 B-0000006-0000010 B 0000008希能在table2写触发器更新table1已用票号,已用票数,结余票号,结余票数的字段。-------------------------------------------------------------------------------------------------------------------- --示例--示例数据 create table table1(序号 int,类别 varchar(10),起始号 char(7),终止号 char(7),总数 int,已用票号 varchar(8000),已用票数 int,结余票号 varchar(8000),结余票数 int,组合编号 varchar(20)) insert table1 select 1,'A','0000001','0000005',5,'',0,'0000001,0000002,0000003,0000004,0000005',5,'A-0000001-0000005' union all select 2,'B','0000006','0000010',5,'',0,'0000006,0000007,0000006,0000009,0000010',5,'B-0000006-0000010'create table table2(组合编号 varchar(20),类别 varchar(10),票号 char(7)) go--处理的触发器 create trigger tr_process on table2 for insert,update,delete as declare @组合编号 varchar(20) ,@sta varchar(8000),@nma int ,@stb varchar(8000),@nmb int--处理被删除的 select d.组合编号,d.票号 ,已用票号=','+a.已用票号+',',a.已用票数 ,结余票号=a.结余票号,a.结余票数 into #d from deleted d,table1 a where d.组合编号=a.组合编号 order by d.组合编号,d.票号if @@rowcount>0 begin update #d set @sta=replace( case 组合编号 when @组合编号 then @sta else 已用票号 end, ','+票号+',',','), @nma=case 组合编号 when @组合编号 then @nma-1 else 已用票数-1 end, @stb=case 组合编号 when @组合编号 then @stb+',' else case 结余票号 when '' then '' else 结余票号+',' end end+票号, @nmb=case 组合编号 when @组合编号 then @nmb+1 else 结余票数+1 end, @组合编号=组合编号, 已用票号=@sta,已用票数=@nma, 结余票号=@stb,结余票数=@nmb update a set 已用票号=case b.已用票数 when 0 then '' else substring(b.已用票号,2,len(b.已用票号)-2) end ,已用票数=b.已用票数 ,结余票号=b.结余票号 ,结余票数=b.结余票数 from table1 a,#d b,( select 组合编号,已用票数=min(已用票数) from #d group by 组合编号 )c where a.组合编号=b.组合编号 and c.组合编号=b.组合编号 and c.已用票数=b.已用票数 end--处理新增的 select i.组合编号,i.票号 ,已用票号=a.已用票号,a.已用票数 ,结余票号=','+a.结余票号+',',a.结余票数 into #i from inserted i,table1 a where i.组合编号=a.组合编号 order by i.组合编号,i.票号if @@rowcount>0 begin set @组合编号=null update #i set @sta=case 组合编号 when @组合编号 then @sta+',' else case 已用票号 when '' then '' else 已用票号+',' end end+票号, @nma=case 组合编号 when @组合编号 then @nma+1 else 已用票数+1 end, @stb=replace( case 组合编号 when @组合编号 then @stb else 结余票号 end, ','+票号+',',','), @nmb=case 组合编号 when @组合编号 then @nmb-1 else 结余票数-1 end, @组合编号=组合编号, 已用票号=@sta,已用票数=@nma, 结余票号=@stb,结余票数=@nmb update a set 已用票号=b.已用票号 ,已用票数=b.已用票数 ,结余票号=case b.结余票数 when 0 then '' else substring(b.结余票号,2,len(b.结余票号)-2) end ,结余票数=b.结余票数 from table1 a,#i b,( select 组合编号,已用票数=max(已用票数) from #i group by 组合编号 )c where a.组合编号=b.组合编号 and c.组合编号=b.组合编号 and c.已用票数=b.已用票数 end go--插入数据测试 insert table2 select 'A-0000001-0000005','A','0000001' union all select 'A-0000001-0000005','A','0000003' union all select 'B-0000006-0000010','B','0000006' union all select 'B-0000006-0000010','B','0000008'--删除测试 delete from table2 where 票号='0000008'--更新测试 update table2 set 票号='0000008' where 票号='0000006' go--显示处理结果 select * from table1 go--删除测试 drop table table1,table2/*--测试结果(自己看)--*/
if not object_id('t1') is null drop table t1 Go Create table t1([type] nvarchar(3),[s] nvarchar(5),[e] nvarchar(5)) Insert t1 select N'001',N'0001',N'0020' union all select N'002',N'0001',N'0020' union all select N'004',N'00001',N'00030' Go Select * from t1 --> --> 生成測試數據
if not object_id('t2') is null drop table t2 Go Create table t2([type] nvarchar(3),[s] nvarchar(5),[e] nvarchar(5)) Insert t2 select N'001',N'0001',N'0005' union all select N'001',N'0006',N'0009' union all select N'002',N'0010',N'0012' union all select N'002',N'0015',N'0019' union all select N'004',N'00013',N'00014' union all select N'004',N'00015',N'00020' union all select N'004',N'00025',N'00027' Go Select * from t2--try: declare @n int select @n=max(cast(e as int)-cast(s as int)+1) from t1 exec('select top '+@n+' id=identity(int,1,1) into # from syscolumns select * from (select type,id=right(replicate(''0'',len(s))+ltrim(id),len(s)) from t1,## where id>=cast(s as int) and id<=cast(e as int))a where not exists(select 1 from t2 where type=a.type and cast(id as int) between s and e)')
上面手误,临时表多打了个#。楼主自己去掉下。。declare @n int select @n=max(cast(e as int)-cast(s as int)+1) from t1 exec('select top '+@n+' id=identity(int,1,1) into # from syscolumns select * from (select type,id=right(replicate(''0'',len(s))+ltrim(id),len(s)) from t1,# where id>=cast(s as int) and id<=cast(e as int))a where not exists(select 1 from t2 where type=a.type and cast(id as int) between s and e)')
select * from ( select type,cast(s as int)+1 as s,cast(ss as int)-1 as e from ( select t1.type,t1.s ,min(t2.s) as ss from t1 join t2 on t1.type = t2.type group by t1.type,t1.s union all select t1.type,max(t2.e) as s,t1.e as ss from t1 join t2 on t1.type = t2.type group by t1.type,t1.e union all select a.type,a.e,min(b.s) as ss from t2 a,t2 b where a.type = b.type and b.s >= a.e group by a.type,a.e )t )tt where s<=e order by type,s
前一段代码忘记考虑边界问题了 以下这段可以完成BOSS的功能 但是,数据类型都被处理成了INT型 select * from ( select type,cast(s+1 as char) as s,cast(ss-1 as char) as e from ( select a.type,cast(a.e as int) as s,cast(min(b.s) as int) as ss from t2 a,t2 b where a.type = b.type and b.s >= a.e group by a.type,a.e )t union all select t1.type,cast(t1.s as int) ,cast(min(t2.s) as int)-1 as ss from t1 join t2 on t1.type = t2.type group by t1.type,t1.s union all select t1.type,cast(max(t2.e) as int)+1 as s,t1.e as ss from t1 join t2 on t1.type = t2.type group by t1.type,t1.e)tt where s<=e
select type,max(s) s,e,os,oe from ( select isnull(x.type,y.type) type,x.e s,y.s e,isnull(x.os,y.os) os,isnull(x.oe,y.oe) oe from ( select a.type,a.e,b.s os,b.e oe from t2 a,t1 b where a.type=b.type and a.s >= b.s and a.e<=b.e and not exists (select 1 from t2 where type=a.type and s=a.e+1)) x full join (select a.type,a.s,b.s os,b.e oe from t2 a,t1 b where a.type=b.type and a.s >= b.s and a.e<=b.e and not exists (select 1 from t2 where type=a.type and e=a.s-1) ) y on x.type=y.type and x.os=y.os and x.oe=y.oe and y.s>=x.e ) b group by type,os,oe,e001 0009 NULL 0001 0020 001 NULL 0001 0001 0020 002 0040 NULL 0001 0050 002 NULL 0010 0001 0050 002 0012 0015 0001 0050 002 0019 0025 0001 0050 002 0026 0031 0001 0050 004 00029 NULL 00001 00030 004 NULL 00013 00001 00030 004 00020 00025 00001 00030这个是我写的,感觉效率不高!然后再此基础上就可以算出还可以使用的票了
其实我的逻辑上想来满简单的 解释下数据处理模型。t1 type s e A ssa eea B ssb eebt2 type s e A s1 e1 A s2 e2 ....... 首先,ssa<=s1<=e1<=s2<=e2<=.......<=eea 区间表示就是: ssa s1--e1 s2--e2 ..... eea “--”表示已经使用的区段 要得到的是“--”区段 ssa----s1 e1----s2 e2--......--eea实际上,只要把s1换到eea的位置,把s2\e1互换位置,再做相应的+-处理就可以了最终的结果表: FT TYPE S E A ssa s1-1 A e1+1 s2-1 ...... A e.last+1 eea
序号 类别 起始号 终止号 总数 已用票号 已用票数 结余票号 结余票数 组合编号(主键)
1 A 0000001 0000005 5 0000001,0000003 2 0000002,0000004,0000005 3
A-0000001-0000005
2 B 0000006 00000010 5 0000006,0000008 2 0000007,0000009,0000010 3 B-0000006-0000010
table2
组合编号 类别 票号
A-0000001-0000005 A 0000001
A-0000001-0000005 A 0000003
B-0000006-0000010 B 0000006
B-0000006-0000010 B 0000008希能在table2写触发器更新table1已用票号,已用票数,结余票号,结余票数的字段。--------------------------------------------------------------------------------------------------------------------
--示例--示例数据
create table table1(序号 int,类别 varchar(10),起始号 char(7),终止号 char(7),总数 int,已用票号 varchar(8000),已用票数 int,结余票号 varchar(8000),结余票数 int,组合编号 varchar(20))
insert table1 select 1,'A','0000001','0000005',5,'',0,'0000001,0000002,0000003,0000004,0000005',5,'A-0000001-0000005'
union all select 2,'B','0000006','0000010',5,'',0,'0000006,0000007,0000006,0000009,0000010',5,'B-0000006-0000010'create table table2(组合编号 varchar(20),类别 varchar(10),票号 char(7))
go--处理的触发器
create trigger tr_process on table2
for insert,update,delete
as
declare @组合编号 varchar(20)
,@sta varchar(8000),@nma int
,@stb varchar(8000),@nmb int--处理被删除的
select d.组合编号,d.票号
,已用票号=','+a.已用票号+',',a.已用票数
,结余票号=a.结余票号,a.结余票数
into #d
from deleted d,table1 a
where d.组合编号=a.组合编号
order by d.组合编号,d.票号if @@rowcount>0
begin
update #d set
@sta=replace(
case 组合编号 when @组合编号 then @sta else 已用票号 end,
','+票号+',',','),
@nma=case 组合编号 when @组合编号 then @nma-1 else 已用票数-1 end,
@stb=case 组合编号 when @组合编号 then @stb+','
else case 结余票号 when '' then '' else 结余票号+',' end end+票号,
@nmb=case 组合编号 when @组合编号 then @nmb+1 else 结余票数+1 end,
@组合编号=组合编号,
已用票号=@sta,已用票数=@nma,
结余票号=@stb,结余票数=@nmb update a set 已用票号=case b.已用票数 when 0 then ''
else substring(b.已用票号,2,len(b.已用票号)-2) end
,已用票数=b.已用票数
,结余票号=b.结余票号
,结余票数=b.结余票数
from table1 a,#d b,(
select 组合编号,已用票数=min(已用票数)
from #d
group by 组合编号
)c where a.组合编号=b.组合编号
and c.组合编号=b.组合编号
and c.已用票数=b.已用票数
end--处理新增的
select i.组合编号,i.票号
,已用票号=a.已用票号,a.已用票数
,结余票号=','+a.结余票号+',',a.结余票数
into #i
from inserted i,table1 a
where i.组合编号=a.组合编号
order by i.组合编号,i.票号if @@rowcount>0
begin
set @组合编号=null
update #i set
@sta=case 组合编号 when @组合编号 then @sta+','
else case 已用票号 when '' then '' else 已用票号+',' end end+票号,
@nma=case 组合编号 when @组合编号 then @nma+1 else 已用票数+1 end,
@stb=replace(
case 组合编号 when @组合编号 then @stb else 结余票号 end,
','+票号+',',','),
@nmb=case 组合编号 when @组合编号 then @nmb-1 else 结余票数-1 end,
@组合编号=组合编号,
已用票号=@sta,已用票数=@nma,
结余票号=@stb,结余票数=@nmb update a set 已用票号=b.已用票号
,已用票数=b.已用票数
,结余票号=case b.结余票数 when 0 then ''
else substring(b.结余票号,2,len(b.结余票号)-2) end
,结余票数=b.结余票数
from table1 a,#i b,(
select 组合编号,已用票数=max(已用票数)
from #i
group by 组合编号
)c where a.组合编号=b.组合编号
and c.组合编号=b.组合编号
and c.已用票数=b.已用票数
end
go--插入数据测试
insert table2 select 'A-0000001-0000005','A','0000001'
union all select 'A-0000001-0000005','A','0000003'
union all select 'B-0000006-0000010','B','0000006'
union all select 'B-0000006-0000010','B','0000008'--删除测试
delete from table2 where 票号='0000008'--更新测试
update table2 set 票号='0000008' where 票号='0000006'
go--显示处理结果
select * from table1
go--删除测试
drop table table1,table2/*--测试结果(自己看)--*/
if not object_id('t1') is null
drop table t1
Go
Create table t1([type] nvarchar(3),[s] nvarchar(5),[e] nvarchar(5))
Insert t1
select N'001',N'0001',N'0020' union all
select N'002',N'0001',N'0020' union all
select N'004',N'00001',N'00030'
Go
Select * from t1
--> --> 生成測試數據
if not object_id('t2') is null
drop table t2
Go
Create table t2([type] nvarchar(3),[s] nvarchar(5),[e] nvarchar(5))
Insert t2
select N'001',N'0001',N'0005' union all
select N'001',N'0006',N'0009' union all
select N'002',N'0010',N'0012' union all
select N'002',N'0015',N'0019' union all
select N'004',N'00013',N'00014' union all
select N'004',N'00015',N'00020' union all
select N'004',N'00025',N'00027'
Go
Select * from t2--try:
declare @n int
select @n=max(cast(e as int)-cast(s as int)+1) from t1
exec('select top '+@n+' id=identity(int,1,1) into # from syscolumns
select * from
(select type,id=right(replicate(''0'',len(s))+ltrim(id),len(s)) from t1,## where id>=cast(s as int) and id<=cast(e as int))a
where not exists(select 1 from t2 where type=a.type and cast(id as int) between s and e)')
select @n=max(cast(e as int)-cast(s as int)+1) from t1
exec('select top '+@n+' id=identity(int,1,1) into # from syscolumns
select * from
(select type,id=right(replicate(''0'',len(s))+ltrim(id),len(s)) from t1,# where id>=cast(s as int) and id<=cast(e as int))a
where not exists(select 1 from t2 where type=a.type and cast(id as int) between s and e)')
002 0001 0009
002 0013 0014
002 0020 0030
002 0041 0050
004 00001 00012
004 00021 00024
004 00028 00030
from
(
select type,cast(s as int)+1 as s,cast(ss as int)-1 as e
from
(
select t1.type,t1.s ,min(t2.s) as ss
from t1 join t2
on t1.type = t2.type
group by t1.type,t1.s
union all
select t1.type,max(t2.e) as s,t1.e as ss
from t1 join t2
on t1.type = t2.type
group by t1.type,t1.e
union all
select a.type,a.e,min(b.s) as ss
from t2 a,t2 b
where a.type = b.type
and b.s >= a.e
group by a.type,a.e
)t
)tt
where s<=e
order by type,s
以下这段可以完成BOSS的功能
但是,数据类型都被处理成了INT型
select *
from
(
select type,cast(s+1 as char) as s,cast(ss-1 as char) as e
from
(
select a.type,cast(a.e as int) as s,cast(min(b.s) as int) as ss
from t2 a,t2 b
where a.type = b.type
and b.s >= a.e
group by a.type,a.e
)t
union all
select t1.type,cast(t1.s as int) ,cast(min(t2.s) as int)-1 as ss
from t1 join t2
on t1.type = t2.type
group by t1.type,t1.s
union all
select t1.type,cast(max(t2.e) as int)+1 as s,t1.e as ss
from t1 join t2
on t1.type = t2.type
group by t1.type,t1.e)tt
where s<=e
select type,max(s) s,e,os,oe from (
select isnull(x.type,y.type) type,x.e s,y.s e,isnull(x.os,y.os) os,isnull(x.oe,y.oe) oe from (
select a.type,a.e,b.s os,b.e oe from t2 a,t1 b where a.type=b.type and a.s >= b.s and a.e<=b.e
and not exists (select 1 from t2 where type=a.type and s=a.e+1)) x
full join
(select a.type,a.s,b.s os,b.e oe from t2 a,t1 b where a.type=b.type and a.s >= b.s and a.e<=b.e
and not exists (select 1 from t2 where type=a.type and e=a.s-1)
) y
on x.type=y.type and x.os=y.os and x.oe=y.oe and y.s>=x.e ) b
group by type,os,oe,e001 0009 NULL 0001 0020
001 NULL 0001 0001 0020
002 0040 NULL 0001 0050
002 NULL 0010 0001 0050
002 0012 0015 0001 0050
002 0019 0025 0001 0050
002 0026 0031 0001 0050
004 00029 NULL 00001 00030
004 NULL 00013 00001 00030
004 00020 00025 00001 00030这个是我写的,感觉效率不高!然后再此基础上就可以算出还可以使用的票了
解释下数据处理模型。t1
type s e
A ssa eea
B ssb eebt2
type s e
A s1 e1
A s2 e2
.......
首先,ssa<=s1<=e1<=s2<=e2<=.......<=eea
区间表示就是:
ssa s1--e1 s2--e2 ..... eea
“--”表示已经使用的区段
要得到的是“--”区段
ssa----s1 e1----s2 e2--......--eea实际上,只要把s1换到eea的位置,把s2\e1互换位置,再做相应的+-处理就可以了最终的结果表:
FT
TYPE S E
A ssa s1-1
A e1+1 s2-1
......
A e.last+1 eea
然后根据E>=S做最后的选择
最后就事数据转换的问题