微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有办法为 SQL 中的特定 ID 生成下一个字母“序列代码”?

如何解决有没有办法为 SQL 中的特定 ID 生成下一个字母“序列代码”?

我从这个 Question 中得到了一些帮助,仍然需要一些进一步的帮助。

我们如何编写一个 sql 函数,它可以只为状态为“A”的 ID 生成 Next Sequence_Code。

注意:如果表已经有Some Sequence_Code,就应该保持原样,不应该有任何变化,但如果表中没有Sequence_Code, 然后函数应该生成一个 Sequence_Code。即在生成 Sequence_Code 之前,它 应该检查前一个 Sequence_Code,然后它应该生成一个。 对于每个新 ID(状态为 'A'),它应该生成一个 Sequence_Code。

字母 'Sequence_Code' 必须是 'Current_Year' 的最后两位数字和 2 个字符的字母组合,如 AA,AB,AC....AZ, BA,BB,BC...BZ。 CA,CB,CC....

例如:如果 Current_Year 是 2017,那么 Sequence_Code 应该是 17AA。

我的表是“LoadData”:

Sequence_Code ID Current_Year Record_Date 状态
17AA 310001 2017 2017-01-01 S
18AB 310002 2018 2018-02-22 S
19AC 310003 2019 2019-02-10 S
公元20年 310004 2019 2019-02-20 A
20AE 310005 2020 2020-03-20 S
NULL 310006 2020 2020-04-20 A

预期输出为:

Sequence_Code ID Current_Year Record_Date 状态
17AA 310001 2017 2017-01-01 S
18AB 310002 2018 2018-02-22 S
19AC 310003 2019 2019-02-10 S
公元20年 310004 2019 2019-02-20 A
20AE 310005 2020 2020-03-20 S
20AF 310006 2020 2020-04-20 A

有什么方便的方法请大家指教。

解决方法

这个比较复杂。我首先将所有对生成为两个字符。然后执行以下操作:

  • 按字母顺序枚举所有代码。
  • 查找当前使用的最大代码。
  • 枚举没有序列码的行
  • 与枚举的代码匹配。

这适用于任意数量的 NULL 值。

作为 select,这看起来像:

with alphas as (
      select convert(char(1),'A') as chr
      union all
      select char(ascii(chr) + 1)
      from alphas
      where chr < 'Z'
     ),alpha2 as (
      select concat(a1.chr,a2.chr) as alpha2,row_number() over (order by a1.chr,a2.chr) as seqnum
      from alphas a1 cross join alphas a2
     )
select lda.*,alpha2.alpha2
from (select row_number() over (order by Current_Year,id) as seqnum,alpha2.seqnum as alpha2_maxseqnum,ld.*
      from (select ld.*,max(right(ld.Sequence_Code,2)) over () as max_seq2
            from loaddata ld 
           ) ld join
           alpha2
           on alpha2.alpha2 = max_seq2
      where ld.Sequence_Code is null
     ) lda join
     alpha2 
     on lda.seqnum = alpha2.seqnum - lda.alpha2_maxseqnum ;

作为update

with alphas as (
      select convert(char(1),a2.chr) as seqnum
      from alphas a1 cross join alphas a2
     ),toupdate as (
      select lda.*,alpha2.alpha2
      from (select row_number() over (order by Current_Year,ld.*
            from (select ld.*,2)) over () as max_seq2
                  from loaddata ld 
                 ) ld join
                 alpha2
                 on alpha2.alpha2 = max_seq2
            where ld.Sequence_Code is null
           ) lda join
           alpha2 
           on lda.seqnum = alpha2.seqnum - lda.alpha2_maxseqnum 
      )
update toupdate
    set Sequence_Code = concat(right(current_year,2),alpha2);

Here 是一个 dbfiddle。

,

您需要为当前条件应用 WHERE 子句:

WITH cte AS (SELECT *,ROW_NUMBER() OVER (ORDER BY Record_Date) rn FROM LoadData)
UPDATE cte
SET Sequence_Code = RIGHT(Current_Year,2) + 
    CHAR(ASCII('A') + rn / 26 + CASE rn % 26 WHEN 0 THEN -1 ELSE 0 END) + 
    CHAR(ASCII('A') - 1 + CASE rn % 26 WHEN 0 THEN 26 ELSE rn % 26 END) 
WHERE Status = 'A' AND Sequence_Code IS NULL

Sequence_Code 是用行号生成的,按照列 Current_Year 的顺序,在表中的每一行。

参见demo
结果:

> Sequence_Code |     ID | Current_Year | Record_Date | Status
> :------------ | -----: | -----------: | :---------- | :-----
> 17AA          | 310001 |         2017 | 2017-01-01  | S     
> 18AB          | 310002 |         2018 | 2018-02-22  | S     
> 19AC          | 310003 |         2019 | 2019-02-10  | S     
> 19AD          | 310004 |         2019 | 2019-02-20  | A     
> 20AE          | 310005 |         2020 | 2020-03-20  | S     
> 20AF          | 310006 |         2020 | 2020-04-20  | A 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。