我需要一个函数来返回字符串中最长的数字序列,例如:
P0123 / 99282返回99282,
P9-123BB-12339返回12339,
12345/54321返回12345(如果长度相同,则应返回第一个实例)。
我已经开发了这个,但是这很慢,我想知道是否有比这更快的东西:
DECLARE @str NVARCHAR(40) = N'P0120993/123-AB1239'
DECLARE @x XML
;WITH e1(n) AS(SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1),
e2(n) AS (SELECT 1 FROM e1 CROSS JOIN (SELECT 1 as t UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1) AS b),
n(Number) AS(SELECT n = ROW_NUMBER() OVER (ORDER BY n) FROM e2)
SELECT @x = CAST(N'<A>'+ REPLACE((SELECT CAST(CAST((
SELECT
CASE WHEN SUBSTRING(@str, Number, 1) like N'[^0-9]' THEN N' ' ELSE SUBSTRING(@str, Number, 1) end
FROM n
WHERE Number <= LEN(@str) FOR XML Path(''))
AS xml) AS nvarchar(max))),N' ',N'</A><A>')+ N'</A>' AS XML)
SELECT TOP 1
case when t.value('.', 'nvarchar(max)') = N'' then null else t.value('.', 'nvarchar(max)') end AS inVal
FROM
@x.nodes('/A') AS x(t)
ORDER BY
LEN(t.value('.', 'nvarchar(max)')) DESC;
说明:
我将通过的字符串的最大长度为40,我要做的是生成一个从一到四十的数字序列,从字符串中提取第N个字符,其中N是序列值,但是如果该字符不是数字,则我用空格替换,然后将XML返回为字符串,并以<A>XXX</A>
然后转换为xml,然后进行查询并以长度dec的形式返回第一项订单。
谢谢
答案 0 :(得分:1)
虽然我不确定100%的性能会提高多少,但这是将字符串分解为任何可能的数字组合并返回长度最长的第一个组合的方法:
DECLARE @foo TABLE(ID varchar(40));
INSERT @foo VALUES('P0123/99282'),('P9-123BB-12339'),('12345/54321');
;WITH NumbersTable AS
(
SELECT TOP (40) n = ROW_NUMBER() OVER (ORDER BY Number)
FROM master.dbo.spt_values
ORDER BY Number
), Results AS
(
SELECT f.Id, SUBSTRING(f.ID, t1.n, t2.n) numericvalues,
row_number() over (partition by f.Id
order by LEN(SUBSTRING(f.ID, t1.n, t2.n)) desc) rn
FROM NumbersTable t1
INNER JOIN @foo AS f
ON t1.n <= LEN(f.ID)
INNER JOIN NumbersTable t2
ON t2.n <= LEN(f.ID)
WHERE SUBSTRING(f.ID, t1.n, t2.n) NOT LIKE '%[^0-9]%'
)
SELECT *
FROM Results
WHERE rn = 1
这将创建一个从1到40的数字表(因为这是您的最大长度),然后使用joins
使用{{1}创建具有数值的数据的每个substring
变体},然后根据该NOT LIKE '%[^0-9]%'
的{{1}}建立一个row_number
。