我必须将数字代码转换为这样的字母代码:
1234-> ABCD
其中0 = 0、1 = A,2 = b等。
这是我的功能以及使用方法:
Create function dbo.DecodeNumToChar
(
@change varchar(10),
@foo varchar(10)
) returns varchar(10)
as
begin
DECLARE @II int = 1,
@result varchar(10)
;WITH x AS
(
SELECT @II as ii, STUFF(@foo,@II,1,SUBSTRING(@change,CAST(SUBSTRING(@foo,@II,1) AS INT)+1,1)) AS AA
UNION ALL
--SELECT @II+1
SELECT ii+1, STUFF(AA,ii+1,1,SUBSTRING(@change,CAST(SUBSTRING(@foo,ii+1,1) AS INT)+1,1)) AS AA
FROM x
where ii+1 <= LEN(@foo)
)
select top 1 @result = AA from x order by ii desc
return @result
end
--------------------------------------------
select brand_code, dbo.DecodeNumToChar('0ABCDEFGHI', brand_code)
from (VALUES('1234'),('5834'),('9905'),('0250')) as t(brand_code)
此功能运行良好,但是在生产数据库中,我们无权创建功能。
我已经尝试过将此功能转换为CTE
declare @change varchar(9) = 'ABCDEFGHI'
DECLARE @II int = 0
;WITH x AS
(
SELECT TOP (10) n = ROW_NUMBER() OVER (ORDER BY Number)
FROM master.dbo.spt_values ORDER BY Number
),
innerCTE as
(
SELECT x.n, SUBSTRING(t.brand_code, x.n, 1) chnum,
case SUBSTRING(t.brand_code, x.n, 1)
when '0' then '0'
else char(65-1+SUBSTRING(t.brand_code, x.n, 1))
end chalfa, t.brand_code
FROM x INNER JOIN (VALUES('1234'),('5834'),('9905'),('0250')) as t(brand_code)
ON x.n <= LEN(t.brand_code)
),
CTE as
(
select n, chnum, chalfa, brand_code, stuff(brand_code, n, 1, chalfa) as code
from innerCTE
union all
select n+1, chnum, chalfa, brand_code, STUFF(code, n+1, 1, chalfa) as code
from cte
where n+1 <= LEN(cte.brand_code)
)
--select * from innerCTE
select * from CTE;
或使用CROSS APPLY这样的示例:Example_1
或将交叉应用与PIVOT一起使用,例如以下示例:Example_2
但是我在SQL方面的经验很差,无法获得正确的结果。
我想要这个:
brand_code decoded_code
1234 ABCD
5834 EHCD
9905 II0E
0250 0BE0
谢谢
答案 0 :(得分:1)
如果使用SQL 2017 +
DECLARE @integerValues TABLE ([I] INT);
INSERT INTO @integerValues ([I])
VALUES
(1234),
(6485834),
(99084705),
(1124601);
SELECT
T.[I],
STRING_AGG(
CASE SUBSTRING(T.[S], V.[number] + 1, 1)
WHEN '9' THEN 'I'
WHEN '8' THEN 'H'
WHEN '7' THEN 'G'
WHEN '6' THEN 'F'
WHEN '5' THEN 'E'
WHEN '4' THEN 'D'
WHEN '3' THEN 'C'
WHEN '2' THEN 'B'
WHEN '1' THEN 'A'
ELSE '0'
END,
'') WITHIN GROUP (ORDER BY T.[I]) [S]
FROM
(SELECT [I], CAST([I] AS VARCHAR(10)) [S] FROM @integerValues) T
JOIN
[master]..[spt_values] V ON V.[number] < LEN(T.[S])
WHERE
V.[type] = 'P';
或者(如果是2016年或更早版本)
DECLARE @integerValues TABLE ([I] INT);
INSERT INTO @integerValues ([I])
VALUES
(1234),
(6485834),
(99084705),
(1124601);
SELECT
[I],
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
CAST([I] AS VARCHAR(10)),
'1',
'A'),
'2',
'B'),
'3',
'C'),
'4',
'D'),
'5',
'E'),
'6',
'F'),
'7',
'G'),
'8',
'H'),
'9',
'I') [S]
FROM
@integerValues;
答案 1 :(得分:0)
以下解决方案对整数值使用<section class="gallery-links">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img1">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img2">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img3">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img4">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img1">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img2">
<img class="gallery-img" src="https://www.w3schools.com/howto/img_forest.jpg" alt="img3">
</section>
子查询和某些mod(FOR XML
)操作来分割每个数字,然后使用映射表将每个数字与一个字符相关联。 %
按顺序返回数字。
FOR XML
结果:
DECLARE @IntegerValues TABLE (Integer INT)
INSERT INTO @IntegerValues (Integer)
VALUES
(1234),
(6485834),
(99084705),
(1124601)
SELECT
T.Integer,
Conversion = (
SELECT
'' + M.Character -- Must have no declared alias (for xml)
FROM
(VALUES
(1, T.Integer % 10),
(2, T.Integer / 10 % 10),
(3, T.Integer / 100 % 10),
(4, T.Integer / 1000 % 10),
(5, T.Integer / 10000 % 10),
(6, T.Integer / 100000 % 10),
(7, T.Integer / 1000000 % 10),
(8, T.Integer / 10000000 % 10),
(9, T.Integer / 100000000 % 10),
(10, T.Integer / 1000000000 % 10),
(11, T.Integer / 10000000000 % 10)
) AS X(OrdinalPosition, SplitDigit)
INNER JOIN (VALUES
(0, '0'),
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D'),
(5, 'E'),
(6, 'F'),
(7, 'G'),
(8, 'H'),
(9, 'I')
) AS M(Digit, Character) ON X.SplitDigit = M.Digit
WHERE
X.OrdinalPosition <= FLOOR(LOG10(T.Integer)) + 1 -- This expression returns the number of digits
ORDER BY
X.OrdinalPosition DESC
FOR XML
PATH('')
)
FROM
@IntegerValues AS T
也许可以使用一种更简洁的方式来编写映射和mod操作,但这应该可以提供一个思路。
答案 2 :(得分:0)
我找到了使用递归CTE的解决方案。
declare @change varchar(10) = '0ABCDEFGHI'
DECLARE @II int = 1;
with BRANDS as
(
select * from (VALUES('1234'),('5834'),('9905'),('0250')) as t(brand_code)
),
CTE as
(
select @II as ii, BRAND_CODE,
STUFF(brand_code,@II,1,SUBSTRING(@change,CAST(SUBSTRING(brand_code,@II,1) AS INT)+1,1)) AS AA
from BRANDS
union all
select c.ii+1, b.BRAND_CODE,
STUFF(AA,c.ii+1,1,SUBSTRING(@change,CAST(SUBSTRING(AA,c.ii+1,1) AS INT)+1,1)) AS AA
from BRANDS b
inner join CTE c on b.BRAND_CODE = c.BRAND_CODE
where c.ii < LEN(b.BRAND_CODE)
)
select BRAND_CODE, AA as NewCode from CTE where ii = len(brand_code) order by BRAND_CODE, ii
答案 3 :(得分:0)
这是@Martin Smith建议使用10个嵌套替换的代码。
DECLARE @change char(10) = '0ABCDEFGHI';
--------------------------------------------
select brand_code,
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( brand_code
, '0', SUBSTRING( @change, 1, 1)) , '1', SUBSTRING( @change, 2, 1))
, '2', SUBSTRING( @change, 3, 1)) , '3', SUBSTRING( @change, 4, 1))
, '4', SUBSTRING( @change, 5, 1)) , '5', SUBSTRING( @change, 6, 1))
, '6', SUBSTRING( @change, 7, 1)) , '7', SUBSTRING( @change, 8, 1))
, '8', SUBSTRING( @change, 9, 1)) , '9', SUBSTRING( @change, 10, 1))
from (VALUES('1234'),('5834'),('9905'),('0250')) as t(brand_code);