今天刚刚在SQL版问的,原帖见http://community.csdn.net/Expert/topic/5207/5207097.xml?temp=.4154932 。这里总结一下。
需求描述:
向各个考点寄考卷,要打印信封上的标签,包括考点代码、考点名称、地址什么的。
比如考点A,要寄805份考卷,由于不可能把所有805份考卷都装到一个信封里,所以打算每个信封装8份,一共装101份。
通过考生表可以得到每个考点各自有多少考生。
查询的结果形式如下:
考点信息(代码、名称、地址等),试卷份数
那么对于上面所举的例子,如何得到:
A(考点各信息),8
A(考点各信息),8
A(考点各信息),8
……
A(考点各信息),8
A(考点各信息),5
(以上结果为101条记录)
不知道我说清楚没
另外,每个信封里面所装的考卷份数,最好也能够灵活变动,比如下次要改成每个里面装5份了。我想上面的功能实现了,这个改成传参数就行了。
初步想法:通过循环,组合出union all的查询,记录在@sql varchar(8000)变量中,但是由于这个有长度限制,太长了就不行了
coolingpipe(冷箫轻笛) 的方法:
--环境
create table tab
(
code int,
name varchar(10)
)
insert into tab select 1,'第一考点'
create table tnum
(
num int
)
declare @i int
set @i = 0
while (@i <= 1000)
begin
insert into tnum select @i
set @i = @i + 1
end
--语句
declare @int int
declare @all int
set @int = 8
set @all = 85
select t1.*,case when @all - t2.num * @int >= 8 then 8 else @all - t2.num * @int end as [试卷份数]
from tab t1 inner join tnum t2 on t2.num * @int <= @all
--结果
code name 试卷份数
----------- ---------- -----------
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 8
1 第一考点 5
(所影响的行数为 11 行)
--删除环境
drop table tab
drop table tnum
dawugui(潇洒老乌龟) 的方法:
if object_id('pubs..tb') is not null
drop table tb
go
create table tb
(
name varchar(20),
cnt int
)
declare @count as int --总数
set @count = 805
declare @per as int --每信封的数量
set @per = 200
declare @i as int --循环变量
set @i = 1
declare @j as int --信封总数
if @count % @per = 0
begin
set @j = @count / @per
while @i <= @j
begin
insert into tb(name,cnt) values('A的信息' , @per)
set @i = @i + 1
end
end
else
begin
set @j = @count / @per
while @i <= @j
begin
insert into tb(name,cnt) values('A的信息' , @per)
set @i = @i + 1
end
insert into tb(name,cnt) values('A的信息' , @count % @per)
end
select * from tb
drop table tb
name cnt
-------------------- -----------
A的信息 200
A的信息 200
A的信息 200
A的信息 200
A的信息 5
(所影响的行数为 5 行)
我最终的解决方案(整个存储过程中的相关部分):
搞定了,写成了存储过程,其中相关部分如下。sbk为考生库,从中可以计算出每个考点的人数。用了辅助表kdbuffer,两个字段:bmddm(报名点代码)和cnt。然后用视图与这个表查询得到最终结果。@per为每个信封的试卷份数,是存储过程的输入参数。@i相当于冷箫轻笛的那个辅助表中的值。
declare @i int
declare @bmddm char(4)
declare @total int
delete from kdbuffer
declare c cursor for select bmddm, count(bmddm) t from sbk group by bmddm
open c
fetch next from c into @bmddm,@total
while @@fetch_status=0
begin
set @i=0
while @i * @per <= @total
begin
insert into kdbuffer
select @bmddm,case when @total - @i * @per >= @per then @per else @total - @i * @per end
set @i=@i+1
end
fetch next from c into @bmddm,@total
end
close c
deallocate c