SQL服务器:如何在最后一次出现另一个子字符串之后和下一个逗号之前找到子字符串
SQL Server: how to find the substring just after the last occurence of another substring and before the next comma
我在 SQL 服务器数据库中有一个 table,其中有一列 ColumnStrings
包含此类字符串:
"AB=ikkw0116,AC=BE D Work stations,AC=BE D stations,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased"
"AB=ikkWA001S1,AC=BE D HD,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased"
"AB=iksw0084,AC=Domain View,AD=pnsas,AD=owned,AD=increased"
"AB=GHRS05900263,AC=Big stations,AC=GHR,AC=BE,AD=ger,AD=eu,AD=intra"
所以我们有一个随机数 AB=
, AC=
和 AD=
.
我想获取最后一次出现 AC=
之后的值(位于等号之后和下一个逗号之前的子字符串)。
在我的示例中,搜索的值将针对这 4 个字符串:
"D Allocated"
"D Allocated"
"Domain View"
"BE"
我可以通过
找到最后一次出现的位置
DATALENGTH(MyTable.[ColumnStrings])-CHARINDEX(REVERSE('=AC'),REVERSE(MyTable.[ColumnStrings]))-1
但是如何获取此 =AC
之后和下一个逗号之前的子字符串(如果我们没有找到任何逗号,则为字符串的末尾)
请不要考虑尝试在您的生产数据库上执行此操作。相反,正如上面的评论所建议的那样,在将 AD 数据引入 SQL 服务器之前对其进行规范化。特别是,SQL 服务器具有 poor/no 正则表达式支持,这是您在这里真正需要的。为此,这里有一个正则表达式模式,您可以使用它来提取键 AC
:
的最终值
^.*\bAC=([^,]+)
您可以将此正则表达式应用于您的数据,然后重新导入。
在像您这样的情况下,基于 JSON 的方法是一种可能的选择。您需要将输入字符串适当地转换为有效的 JSON 结构——嵌套的 JSON 数组(AB=iksw0084,AC=Domain View,AD=pnsas,AD=owned,AD=increased
转换为 [["AB","iksw0084"],["AC","Domain View"],["AD","pnsas"],["AD","owned"],["AD","increased"]
)。然后你需要用 OPENJSON()
和默认模式解析这个 JSON 。结果是一个 table,其中包含 key
、value
和 type
列,如果是数组,key
列包含每个项目的从 0 开始的索引在数组中。这个想法是将此索引用于 ROW_NUMBER()
调用中的 ORDER BY
子句。
Table:
SELECT ColumnStrings
INTO Data
FROM (VALUES
('AB=ikkw0116,AC=BE D Work stations,AC=BE D stations,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased'),
('AB=ikkWA001S1,AC=BE D HD,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased'),
('AB=iksw0084,AC=Domain View,AD=pnsas,AD=owned,AD=increased'),
('AB=GHRS05900263,AC=Big stations,AC=GHR,AC=BE,AD=ger,AD=eu,AD=intra')
) v (ColumnStrings)
声明:
SELECT j.StringValue
FROM Data d
OUTER APPLY (
SELECT
j1.[value],
JSON_VALUE([value], '$[0]') AS StringKey,
JSON_VALUE([value], '$[1]') AS StringValue,
ROW_NUMBER() OVER (
PARTITION BY JSON_VALUE([value], '$[0]')
ORDER BY CONVERT(int, [key]) DESC
) AS RN
FROM OPENJSON(CONCAT('[["', REPLACE(REPLACE(d.ColumnStrings, ',', '"],["'), '=', '","'), '"]]')) j1
) j
WHERE j.StringKey = 'AC' AND j.RN = 1
结果:
StringValue
-----------
D Allocated
D Allocated
Domain View
BE
我在 SQL 服务器数据库中有一个 table,其中有一列 ColumnStrings
包含此类字符串:
"AB=ikkw0116,AC=BE D Work stations,AC=BE D stations,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased"
"AB=ikkWA001S1,AC=BE D HD,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased"
"AB=iksw0084,AC=Domain View,AD=pnsas,AD=owned,AD=increased"
"AB=GHRS05900263,AC=Big stations,AC=GHR,AC=BE,AD=ger,AD=eu,AD=intra"
所以我们有一个随机数 AB=
, AC=
和 AD=
.
我想获取最后一次出现 AC=
之后的值(位于等号之后和下一个逗号之前的子字符串)。
在我的示例中,搜索的值将针对这 4 个字符串:
"D Allocated"
"D Allocated"
"Domain View"
"BE"
我可以通过
找到最后一次出现的位置DATALENGTH(MyTable.[ColumnStrings])-CHARINDEX(REVERSE('=AC'),REVERSE(MyTable.[ColumnStrings]))-1
但是如何获取此 =AC
之后和下一个逗号之前的子字符串(如果我们没有找到任何逗号,则为字符串的末尾)
请不要考虑尝试在您的生产数据库上执行此操作。相反,正如上面的评论所建议的那样,在将 AD 数据引入 SQL 服务器之前对其进行规范化。特别是,SQL 服务器具有 poor/no 正则表达式支持,这是您在这里真正需要的。为此,这里有一个正则表达式模式,您可以使用它来提取键 AC
:
^.*\bAC=([^,]+)
您可以将此正则表达式应用于您的数据,然后重新导入。
在像您这样的情况下,基于 JSON 的方法是一种可能的选择。您需要将输入字符串适当地转换为有效的 JSON 结构——嵌套的 JSON 数组(AB=iksw0084,AC=Domain View,AD=pnsas,AD=owned,AD=increased
转换为 [["AB","iksw0084"],["AC","Domain View"],["AD","pnsas"],["AD","owned"],["AD","increased"]
)。然后你需要用 OPENJSON()
和默认模式解析这个 JSON 。结果是一个 table,其中包含 key
、value
和 type
列,如果是数组,key
列包含每个项目的从 0 开始的索引在数组中。这个想法是将此索引用于 ROW_NUMBER()
调用中的 ORDER BY
子句。
Table:
SELECT ColumnStrings
INTO Data
FROM (VALUES
('AB=ikkw0116,AC=BE D Work stations,AC=BE D stations,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased'),
('AB=ikkWA001S1,AC=BE D HD,AC=D Allocated,AD=pnser,AD=pnsas,AD=owned,AD=increased'),
('AB=iksw0084,AC=Domain View,AD=pnsas,AD=owned,AD=increased'),
('AB=GHRS05900263,AC=Big stations,AC=GHR,AC=BE,AD=ger,AD=eu,AD=intra')
) v (ColumnStrings)
声明:
SELECT j.StringValue
FROM Data d
OUTER APPLY (
SELECT
j1.[value],
JSON_VALUE([value], '$[0]') AS StringKey,
JSON_VALUE([value], '$[1]') AS StringValue,
ROW_NUMBER() OVER (
PARTITION BY JSON_VALUE([value], '$[0]')
ORDER BY CONVERT(int, [key]) DESC
) AS RN
FROM OPENJSON(CONCAT('[["', REPLACE(REPLACE(d.ColumnStrings, ',', '"],["'), '=', '","'), '"]]')) j1
) j
WHERE j.StringKey = 'AC' AND j.RN = 1
结果:
StringValue
-----------
D Allocated
D Allocated
Domain View
BE