首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

求最小空号算法!解决方法

2012-02-14 
求最小空号算法!假设表tb(idvarchar(4)),id可重复。1.有1(001)的记录a(不连续). A001 , A001 , A003

求最小空号算法!
假设表tb(id   varchar(4)),id可重复。
1.有1(001)的记录
a(不连续). "A001 ", "A001 ", "A003 "-> 取得 "A002 "
b(连续的). "B001 ", "B002 "-> 取得 "B003 "
2.没有1的记录
"C003 "-> 取得 "C001 "
3.没有的记录
假设 "Dxxx "是不存在的-> 取得 "D001 "

现在要得到ABCD各类的最小空号就是 "A002 ", "B003 ", "C001 ", "D001 "

请大虾指教,第2点没弄出来-_-#!...


[解决办法]
没太看明白。
就2、3点
if not exist (select * from tb where id= 'A001 ')
print 'A001 '
B001,C001,D001类似

希望对你有帮助


[解决办法]
有办法,就是杂建立一个表,当你删除一个号的时候,就在这个表建立一条记录,
插入的时候,先找这个表的记录,如果没有,再找最大记录
[解决办法]
declare @t table(code varchar(6))
insert into @t select 'A001 '
insert into @t select 'A001 '
insert into @t select 'A003 '
insert into @t select 'B001 '
insert into @t select 'B002 '
insert into @t select 'C003 '

select
a.m+right( '000 '+rtrim(min(a.n)+1),3) as newCode
from
(select left(code,1) as m,cast(right(code,3) as int) n from @t) a
where
not exists(select 1 from @t where left(code,1)=a.m and right(code,3)=a.n+1)
group by
a.m
union
select char(ascii(max(left(code,1)))+1)+ '001 ' from @t


/*
newCode
--------
A002
B003
C004
D001
*/
[解决办法]
CREATE TABLE T1(COL VARCHAR(10))
INSERT INTO T1 VALUES( 'A001 ')
INSERT INTO T1 VALUES( 'A001 ')
INSERT INTO T1 VALUES( 'A003 ')
INSERT INTO T1 VALUES( 'B001 ')
INSERT INTO T1 VALUES( 'B002 ')
INSERT INTO T1 VALUES( 'C003 ')
GO
CREATE PROCEDURE P(@COL CHAR(1))
AS
DECLARE @S VARCHAR(10)
DECLARE @T TABLE(ID INT IDENTITY(1,1),COL VARCHAR(10))
INSERT INTO @T
SELECT TOP 999 0 FROM SYSCOLUMNS A,SYSCOLUMNS B
UPDATE @T SET COL=@COL+RIGHT(1000+ID,3)
SELECT @S=MIN(COL) FROM @T A WHERE NOT EXISTS
(SELECT 1 FROM T1 WHERE LEFT(COL,1)=@COL AND COL=A.COL)
SELECT @S
GO
EXEC P 'A '
EXEC P 'B '
EXEC P 'C '
EXEC P 'D '
EXEC P 'F '
DROP TABLE T1
DROP PROCEDURE P

[解决办法]
/*
newCode
--------
A002
B003
C004==========> 应该是C001才对啊
D001
*/

[解决办法]
Debug:
--------------------------------------------------
declare @t table(code varchar(6))
insert into @t select 'A001 '
insert into @t select 'A001 '
insert into @t select 'A003 '
insert into @t select 'B001 '
insert into @t select 'B002 '
insert into @t select 'C003 '

select
a.m+right( '000 '+rtrim(min(a.n)+1),3) as newCode
from
(select left(code,1) as m,cast(right(code,3) as int) n from @t
union
select left(code,1), '000 ' from @t) a
where
not exists(select 1 from @t where left(code,1)=a.m and right(code,3)=a.n+1)
group by
a.m
union


select char(ascii(max(left(code,1)))+1)+ '001 ' from @t

/*
newCode
--------
A002
B003
C001
D001
*/
[解决办法]
佩服
[解决办法]
再佩服一下
[解决办法]
钻石真漂亮
[解决办法]
create table tb([id] varchar(4))

insert tb values( 'A001 ')
insert tb values( 'A001 ')
insert tb values( 'A003 ')
insert tb values( 'B001 ')

insert tb values( 'B002 ')


declare @c char(1) , @cID varchar(4)

select @c = 'A '
if not exists(select 1 from tb where [id]=@c+ '001 ')
begin
select @cID=@c+ '001 '
end
else
begin
select @cID= min([id]) from tb where left([id],1)=@c and cast(right([id],3) as int)+1 not in (select cast(right([id],3) as int) from tb where left([id],1)=@c)
select @cID = @c + right( '000 '+ltrim(rtrim(cast(cast(right(@cID,3) as int)+1 as char(3)))) ,3)
end

select @c,@cID
drop table tb
[解决办法]
MARK!
[解决办法]
呵呵 和我刚做完的咚咚有点象
A01/001 A01/002 A01/003
A02/001 A02/002 A02/003
A03/001 A03/002 A03/003
B01/001 B01/002 B01/003
B02/001 B02/002 B02/003

[解决办法]
这样的题目你们怎么碰到的?
[解决办法]
把A/B/C/D 与后面的数字分开,数字由01开始一直循环到提交的数字,看有空就用啊。再拼起来用。这个题只是复杂一点,并不难
[解决办法]
create Procedure GetNextID(@inStr char(1))
as

declare @mPID char(4),
@mFilter char(2),
@nTmpID int

set @mFilter = @inStr+ '% '
select ID=Identity(int,1,1),a.* into #tmp
from (select distinct Col from t1 where COl like+@mFilter)a

if exists(select top 1 * from #tmp)
begin
select top 1 @nTmpID=ID from #tmp where ID <> Convert(int,right(Col,3))
if @@rowCount=0
select @nTmpID=max(ID)+1 from #tmp

if @nTmpID <10
set @mPID = @inStr+ '00 '+Convert(Char(1),@nTmpID)
else if @nTmpID <100
set @mPID = @inStr+ '0 '+Convert(Char(1),@nTmpID)
else if @nTmpID <1000
set @mPID = @inStr+Convert(Char(1),@nTmpID)

end
else
set @mPID = @inStr+ '001 '

drop table #tmp
select @mPID

Go

--exec GetNextID 'A '
--exec GetNextID 'B '
--exec GetNextID 'C '
--exec GetNextID 'D '
[解决办法]
佩服!!
[解决办法]
mark
[解决办法]
libin_ftsafe(子陌红尘)回帖的语句不具有通用性,比如
union
select char(ascii(max(left(code,1)))+1)+ '001 ' from @t
确实输出了D001这个值,但只适用于帖子中这个例子,因为他的语句会直接产生一条某类001的结果,该类字母比原数据中出现的最大字母大1。
如果数据中C类中没有数据,而D类中有D001,那么他的语句执行结果会有以下错误:
1. 没有C001的输出
2. 出现了E001输出,而E类是不存在的。


[解决办法]
正确的解法是:
1. 首先得有一个专门的表指出你所有的类名,因为这个题目要求未出现的项,即集合的补集,那就先得给出全集。例如是A B C D, 还是A B C D E F, 或者根本没有规律如A E G T X Y。假设这个表名是CLASSNAME。
2. 想办法把你的三种情况变成一种,这样就可用一条SQL语句来产生输出。办法很简单,在你的原数据中加入所有类的000纪录,实际上,这是一种修改边界条件的方法,这样一来,只有一种情况了,那就是查找最小的未使用编号了。语句如下(假设你的数据表名是CLASSDATA)
select left(code,1) as m,cast(right(code,3) as int) n from CLASSDATA
union
select CODE,0 from CLASSNAME
3. 对上面语句产生的表做查询,找出每类中后面没有连续值的所有编号中最小的那个,具体写法可参见libin_ftsafe(子陌红尘)回帖的语句。

[解决办法]
做个总结:
declare @t table(code varchar(6))
insert into @t select 'A001 '
insert into @t select 'A001 '
insert into @t select 'A003 '
insert into @t select 'B001 '
insert into @t select 'B002 '
insert into @t select 'D003 '

declare @s table(code varchar(6))
insert into @s
select 'A ' union all
select 'B ' union all
select 'C ' union all
select 'D ' union all
select 'F '

select
a.m+right(rtrim(min(a.n)+1001),3) as newCode
from
(select left(code,1) as m,cast(right(code,3) as int) n from @t
union
select code,0 from @s) a LEFT JOIN @t B on left(B.code,1)=a.m and right(B.code,3)=a.n+1
where B.code is null
group by
a.m

热点排行