有没有办法为 SQL 中的特定 ID 生成下一个字母 'Sequence Code'?
Is there any way to generate Next Alphabetic 'Sequence Code' For Specific ID's In SQL?
我从中得到了一些帮助,还需要一些进一步的帮助。
我们如何编写一个 SQL 函数,它可以只为那些具有状态 'A' 的 ID 生成下一个 Sequence_Code。
注意:如果Table已经有一些Sequence_Code,应该是这样,不应该有任何变化,但是如果Sequence_Code在table,
那么函数应该生成下一个 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。
我的 table 是 'LoadData':
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
20AD
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
Status
17AA
310001
2017
2017-01-01
S
18AB
310002
2018
2018-02-22
S
19AC
310003
2019
2019-02-10
S
20AD
310004
2019
2019-02-20
A
20AE
310005
2020
2020-03-20
S
20AF
310006
2020
2020-04-20
A
有方便的方法请指教
您需要为当前条件应用 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
是根据 table 中每一行的行号,按列 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
这个比较复杂。我将从生成所有对到两个字符开始。然后执行以下操作:
- 按字母顺序列举所有代码。
- 查找当前使用的最大代码。
- 枚举没有序号的行
- 匹配回枚举代码。
这适用于任意数量的 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), '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
),
toupdate as (
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 toupdate
set Sequence_Code = concat(right(current_year, 2), alpha2);
Here 是一个 db<>fiddle.
我从中得到了一些帮助
我们如何编写一个 SQL 函数,它可以只为那些具有状态 'A' 的 ID 生成下一个 Sequence_Code。
注意:如果Table已经有一些Sequence_Code,应该是这样,不应该有任何变化,但是如果Sequence_Code在table, 那么函数应该生成下一个 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。
我的 table 是 'LoadData':
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 20AD 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 Status 17AA 310001 2017 2017-01-01 S 18AB 310002 2018 2018-02-22 S 19AC 310003 2019 2019-02-10 S 20AD 310004 2019 2019-02-20 A 20AE 310005 2020 2020-03-20 S 20AF 310006 2020 2020-04-20 A
有方便的方法请指教
您需要为当前条件应用 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
是根据 table 中每一行的行号,按列 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
这个比较复杂。我将从生成所有对到两个字符开始。然后执行以下操作:
- 按字母顺序列举所有代码。
- 查找当前使用的最大代码。
- 枚举没有序号的行
- 匹配回枚举代码。
这适用于任意数量的 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), '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
),
toupdate as (
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 toupdate
set Sequence_Code = concat(right(current_year, 2), alpha2);
Here 是一个 db<>fiddle.