4

我已经在 nvarchar 列中填充了一些字符串值。字符串的格式是这样的:

例如:16B、23G、128F、128M等...

我需要从中找出最大值,然后从代码中生成下一个。拾取最大物品的逻辑如下:

  1. 拿起数字最大的字符串。
  2. 如果多个最大的数字,然后拿起其中最大的字母字符串。

例如,上述系列中最大的字符串是 128M。

现在我需要生成下一个序列。下一个字符串将有

  1. 与最大的数字相同,但字母加 1。IE 128N
  2. 如果字母到达Z,则数字加1,字母为A。例如,128Z的下一个字符串是129A。

谁能让我知道什么样的 SQL 可以得到我想要的字符串。

4

5 回答 5

5

如果您可以更改表定义(*),则保持基本值完全是数字并仅格式化为这些字符串会更容易:

create table T (
    CoreValue int not null,
    DisplayValue as CONVERT(varchar(10),(CoreValue / 26)+1) + CHAR(ASCII('A') + (CoreValue-1) % 26)
)
go
insert into T (CoreValue)
select ROW_NUMBER() OVER (ORDER BY so1.object_id)
from sys.objects so1,sys.objects so2
go
select * from T

结果:

CoreValue   DisplayValue
----------- ------------
1           1A
2           1B
3           1C
4           1D
5           1E
6           1F
....
22          1V
23          1W
24          1X
25          1Y
26          2Z
27          2A
28          2B
29          2C
....
9593        369Y
9594        370Z
9595        370A
9596        370B
9597        370C
9598        370D
9599        370E
9600        370F
9601        370G
9602        370H
9603        370I
9604        370J

所以插入一个新值就像从列中取出并加1一样简单MAX(假设可序列化隔离或类似,以处理多个用户)


(*) 即使你不能改变你的表定义——我仍然会生成这个表。然后,您可以将其连接到原始表,并可以使用它对列执行简单MAX的操作int,然后添加一个并查找下一个要使用的字母数字值。只需使用您期望使用的尽可能多的值填充它。

于 2012-09-28T14:45:28.377 回答
1

假设:

CREATE TABLE MyTable
    ([Value] varchar(4))
;

INSERT INTO MyTable
    ([Value])
VALUES
    ('16B'),
    ('23G'),
    ('128F'),
    ('128M')
;

你可以做:

select top 1 
    case when SequenceChar = 'Z' then
        cast((SequenceNum + 1) as varchar) + 'A'
    else
        cast(SequenceNum as varchar) + char(ascii(SequenceChar) + 1)
    end as NextSequence
from (
    select Value, 
        cast(substring(Value, 1, CharIndex - 1) as int) as SequenceNum, 
        substring(Value, CharIndex, len(Value)) as SequenceChar
    from (
        select Value, patindex('%[A-Z]%', Value) as CharIndex
        from MyTable
    ) a
) b
order by SequenceNum desc, SequenceChar desc

SQL 小提琴示例

于 2012-09-28T15:05:02.970 回答
0

假设您的列始终遵循您描述的格式(数字+1 字符后缀),您可以这样做

WITH cte1 AS(
SELECT LEFT(your_column,LEN(your_column)-1) as num, 
RIGHT(your_column,1) as suffix
FROM your_table),
cte2 AS (SELECT MAX(num) as max_num FROM cte1)
SELECT 
 CASE c.max_suffix
  WHEN 'Z' THEN 'A'
  ELSE NCHAR(UNICODE(c.max_suffix)+1)
 END as next_suffix,

CASE c.max_suffix
 WHEN 'Z' THEN a.max_num+1
 ELSE a.max_num
END as next_num

FROM  cte2 a 
CROSS APPLY (SELECT MAX(suffix) as max_suffix FROM cte1 b WHERE b.num=a.max_num)c
;

我很确定还有其他方法可以做到这一点。另外,我的方法似乎不是最优的,但我认为它会返回你需要的东西......

毫无疑问,如果您可以按照Damien_The_Unbeliever的建议重新设计表格,那会更好。

于 2012-09-28T14:59:25.483 回答
0

生成以下格式的字母数字字符串序列。AB C......YZ AA AB......AZ BA BB......BZ......继续。

CREATE OR REPLACE FUNCTION to_az(in_num  number)

RETURN VARCHAR2

IS

 num          PLS_INTEGER    := TRUNC (in_num) - 1;
 return_txt     VARCHAR2 (1) := CHR (65 + MOD (num, 26));

BEGIN

 IF  num <= 25
 THEN
      RETURN     return_txt;
 ELSE
      RETURN     to_az (FLOOR (num / 26))
           || return_txt;
 END IF;
END to_az;
于 2013-12-11T11:55:02.450 回答
0

ms-sql 函数生成一个字母数字的下一个序列 id,如 'P0001'、'P0002' 等。

ALTER FUNCTION NextProductID()
 returns varchar(20)
 BEGIN
    DECLARE  @NEXTNUMBER INT;
    DECLARE @NEXTPRODUCTID VARCHAR(20);
 SELECT @NEXTNUMBER=MAX( CONVERT(INT, SUBSTRING(PRODUCT_CODE,2,LEN(PRODUCT_CODE))))+1 FROM Product;
    --PRINT @NEXTNUMBER;
    SET @NEXTPRODUCTID=CONVERT(VARCHAR,@NEXTNUMBER)
    SELECT @NEXTPRODUCTID='P'+REPLICATE('0',6-LEN(@NEXTPRODUCTID)) + @NEXTPRODUCTID;
  return @NEXTPRODUCTID;
END

这里 product 是表名,product_code 是列

于 2014-03-22T16:46:23.907 回答