有人可以帮助我更新 sql server 2019 代码以与 sql server 2008 r2 一起使用吗?
Could someone assist me updating a sql server 2019 code to work with sql server 2008 r2?
我有这段代码 运行 在 sql 服务器 2019 上非常完美,但我认为很多功能只在 2017+ 版本中引入。我正在使用 sql 服务器 2008r2,想知道是否有人可以帮助我将其重新编码为 运行。谢谢。
declare
@s1 varchar(100)='The Elf on the Shelf: A Christmas Musical. (Touring)',
@s2 varchar(100)='The Elf on the Shelf Musical, Baltimore';
with words as (
select 1 s, Replace(Translate(value,'!"*():;,.','|||||||||'),'|','') word
from String_Split(@s1,' ')
union all
select 2, Replace(Translate(value,'!"*():;,.','|||||||||'),'|','')
from String_Split(@s2,' ')
), matching as (
select *, Row_Number() over(partition by word order by s) rn
from words
), final as (
select * , Count(*) over(partition by word, s) repeating, Count(*) over() * 1.0 totwords, sum(Iif(s=1,1,0)) over() s1words
from matching
outer apply(values(Iif(rn=2 and rn=s,1,0)))x(p)
)
select (Sum (p) + max(case when s=1 and repeating>1 then repeating end))
/ Max(Iif(totwords/s1words>0.5, totwords-s1words, s1words)) * 100 [Matching Words %]
from final
要在 SQL Server 2008 R2 中完成相同的工作,效率会大大降低,您将需要创建一些帮助用户定义的函数。
第一个是用于拆分字符串的通用方法,用于替换 STRING_SPLIT()
。实际上有数百种不同的分隔符,但请注意,有些可能无法正确处理 space 作为分隔符。这只是我从 my own stash of resources on splitting strings:
抓取的第一个
CREATE FUNCTION dbo.SplitStrings
(
@List nvarchar(max),
@Delimiter nvarchar(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value(N'(./text())[1]', N'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, N'<i>'
+ REPLACE(@List, @Delimiter, N'</i><i>')
+ N'</i>').query(N'.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
接下来我们需要一个函数来迭代一个字符串,一次一个字符,并删除坏字符(这将替换您现有代码中的 TRANSLATE()
)。一些解决方案将使用 while 循环和 patindex,这没关系,但其他解决方案只会说嵌套 17 REPLACE()
调用,这使得代码无法阅读和维护。这是我想出的:
CREATE FUNCTION dbo.CreateCleanString
(
@String nvarchar(4000),
@IgnorePattern nvarchar(255)
)
RETURNS @Set TABLE
(
listpos int,
character nchar(1)
)
WITH SCHEMABINDING
AS
BEGIN
DECLARE @pos int, @ThisCharacter nchar(1);
SET @pos = 1
WHILE @pos <= LEN(@String)
BEGIN
SET @ThisCharacter = SUBSTRING(@String, @pos, 1);
IF @IgnorePattern NOT LIKE N'%' + @ThisCharacter + N'%'
BEGIN
INSERT @Set(listpos, character)
SELECT COALESCE(MAX(listpos) + 1, 1), SUBSTRING(@String, @pos, 1)
FROM @Set;
END
SET @pos = @pos + 1;
END
RETURN;
END
GO
有了这两个,您现在可以编写这个复杂得多的查询来获得结果。我不打算列举所有差异,但它们从第一行开始(SQL Server 2008 不支持内联 declare/set),然后继续 IIF()
参考重写为 CASE
expressions.
DECLARE @pattern nvarchar(255), @s1 nvarchar(4000), @s2 nvarchar(4000);
SELECT @pattern = N'!"*():;,.',
@s1 = N'The Elf on the Shelf: A Christmas Musical. (Touring)',
@s2 = N'The Elf on the Shelf Musical, Baltimore';
;WITH clean_src AS -- break it apart by character and get rid of bad ones
(
SELECT src.s, src.str, c.listpos, c.character
FROM (VALUES(1,@s1),(2,@s2)) AS src(s,str)
CROSS APPLY dbo.CreateCleanString(src.str, @pattern) AS c),
clean_output AS -- put it back together
(
SELECT s, rn = ROW_NUMBER() OVER (PARTITION BY s ORDER BY c.listpos),
CleanString = (SELECT clean_src.character
FROM clean_src WHERE s = c.s ORDER BY c.listpos
FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(4000)')
FROM clean_src AS c),
words AS -- now break it apart again, this time into words
(
SELECT s, word = Item, rn = ROW_NUMBER() OVER (PARTITION BY Item ORDER BY s)
FROM clean_output CROSS APPLY dbo.SplitStrings(CleanString, ' ')
WHERE rn = 1),
final AS -- do some matching and generate aggregates
(
SELECT s, word, rn, x.p,
repeating = COUNT(*) OVER (PARTITION BY word, s),
totwords = COUNT(*) OVER() * 1.0,
s1words = SUM(CASE WHEN s = 1 THEN 1 ELSE 0 END) OVER()
FROM words
OUTER APPLY (VALUES(CASE WHEN rn = 2 and rn = s THEN 1 ELSE 0 END)) AS x(p)
)
SELECT [Matching Words %] = (SUM(p)
+ MAX(CASE WHEN s = 1 AND repeating > 1 THEN repeating END))
/ MAX(CASE WHEN totwords / s1words > 0.5 THEN totwords - s1words
ELSE s1words END) * 100
FROM final;
- SQL Server 2019 上的原始版本:db<>fiddle
- 此方法,支持的最旧版本 (2014):db<>fiddle
现在,我没有 SQL Server 2008 R2 实例来对此进行测试,事实上,我四处询问,但我不知道还有谁这样做。真的是时候考虑最终升级了,恕我直言。
我有这段代码 运行 在 sql 服务器 2019 上非常完美,但我认为很多功能只在 2017+ 版本中引入。我正在使用 sql 服务器 2008r2,想知道是否有人可以帮助我将其重新编码为 运行。谢谢。
declare
@s1 varchar(100)='The Elf on the Shelf: A Christmas Musical. (Touring)',
@s2 varchar(100)='The Elf on the Shelf Musical, Baltimore';
with words as (
select 1 s, Replace(Translate(value,'!"*():;,.','|||||||||'),'|','') word
from String_Split(@s1,' ')
union all
select 2, Replace(Translate(value,'!"*():;,.','|||||||||'),'|','')
from String_Split(@s2,' ')
), matching as (
select *, Row_Number() over(partition by word order by s) rn
from words
), final as (
select * , Count(*) over(partition by word, s) repeating, Count(*) over() * 1.0 totwords, sum(Iif(s=1,1,0)) over() s1words
from matching
outer apply(values(Iif(rn=2 and rn=s,1,0)))x(p)
)
select (Sum (p) + max(case when s=1 and repeating>1 then repeating end))
/ Max(Iif(totwords/s1words>0.5, totwords-s1words, s1words)) * 100 [Matching Words %]
from final
要在 SQL Server 2008 R2 中完成相同的工作,效率会大大降低,您将需要创建一些帮助用户定义的函数。
第一个是用于拆分字符串的通用方法,用于替换 STRING_SPLIT()
。实际上有数百种不同的分隔符,但请注意,有些可能无法正确处理 space 作为分隔符。这只是我从 my own stash of resources on splitting strings:
CREATE FUNCTION dbo.SplitStrings
(
@List nvarchar(max),
@Delimiter nvarchar(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value(N'(./text())[1]', N'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, N'<i>'
+ REPLACE(@List, @Delimiter, N'</i><i>')
+ N'</i>').query(N'.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
接下来我们需要一个函数来迭代一个字符串,一次一个字符,并删除坏字符(这将替换您现有代码中的 TRANSLATE()
)。一些解决方案将使用 while 循环和 patindex,这没关系,但其他解决方案只会说嵌套 17 REPLACE()
调用,这使得代码无法阅读和维护。这是我想出的:
CREATE FUNCTION dbo.CreateCleanString
(
@String nvarchar(4000),
@IgnorePattern nvarchar(255)
)
RETURNS @Set TABLE
(
listpos int,
character nchar(1)
)
WITH SCHEMABINDING
AS
BEGIN
DECLARE @pos int, @ThisCharacter nchar(1);
SET @pos = 1
WHILE @pos <= LEN(@String)
BEGIN
SET @ThisCharacter = SUBSTRING(@String, @pos, 1);
IF @IgnorePattern NOT LIKE N'%' + @ThisCharacter + N'%'
BEGIN
INSERT @Set(listpos, character)
SELECT COALESCE(MAX(listpos) + 1, 1), SUBSTRING(@String, @pos, 1)
FROM @Set;
END
SET @pos = @pos + 1;
END
RETURN;
END
GO
有了这两个,您现在可以编写这个复杂得多的查询来获得结果。我不打算列举所有差异,但它们从第一行开始(SQL Server 2008 不支持内联 declare/set),然后继续 IIF()
参考重写为 CASE
expressions.
DECLARE @pattern nvarchar(255), @s1 nvarchar(4000), @s2 nvarchar(4000);
SELECT @pattern = N'!"*():;,.',
@s1 = N'The Elf on the Shelf: A Christmas Musical. (Touring)',
@s2 = N'The Elf on the Shelf Musical, Baltimore';
;WITH clean_src AS -- break it apart by character and get rid of bad ones
(
SELECT src.s, src.str, c.listpos, c.character
FROM (VALUES(1,@s1),(2,@s2)) AS src(s,str)
CROSS APPLY dbo.CreateCleanString(src.str, @pattern) AS c),
clean_output AS -- put it back together
(
SELECT s, rn = ROW_NUMBER() OVER (PARTITION BY s ORDER BY c.listpos),
CleanString = (SELECT clean_src.character
FROM clean_src WHERE s = c.s ORDER BY c.listpos
FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(4000)')
FROM clean_src AS c),
words AS -- now break it apart again, this time into words
(
SELECT s, word = Item, rn = ROW_NUMBER() OVER (PARTITION BY Item ORDER BY s)
FROM clean_output CROSS APPLY dbo.SplitStrings(CleanString, ' ')
WHERE rn = 1),
final AS -- do some matching and generate aggregates
(
SELECT s, word, rn, x.p,
repeating = COUNT(*) OVER (PARTITION BY word, s),
totwords = COUNT(*) OVER() * 1.0,
s1words = SUM(CASE WHEN s = 1 THEN 1 ELSE 0 END) OVER()
FROM words
OUTER APPLY (VALUES(CASE WHEN rn = 2 and rn = s THEN 1 ELSE 0 END)) AS x(p)
)
SELECT [Matching Words %] = (SUM(p)
+ MAX(CASE WHEN s = 1 AND repeating > 1 THEN repeating END))
/ MAX(CASE WHEN totwords / s1words > 0.5 THEN totwords - s1words
ELSE s1words END) * 100
FROM final;
- SQL Server 2019 上的原始版本:db<>fiddle
- 此方法,支持的最旧版本 (2014):db<>fiddle
现在,我没有 SQL Server 2008 R2 实例来对此进行测试,事实上,我四处询问,但我不知道还有谁这样做。真的是时候考虑最终升级了,恕我直言。