删除一个字符之后的字符串的一部分直到一个字符并重复直到字符串结束
Remove part of a string after a character until a charcter and repeat until the string end
我正在尝试过滤字符串的一部分直到它到达特定字符并重复直到字符串结束。
数据看起来像
095930
CF0010+EN
060983+PS
086588+GG;086326+GG
900010;
CF0002;;CF0018;
输出应该是
095930
CF0010
060983
086588;086326
900010;
CF0002;;CF0018;
我尝试了以下方法:
SUBSTRING(column, 1, CHARINDEX('+',column+ '+', 1)-1)
但这会删除 +
之后的所有内容,这不是我需要的。
删除后面的所有内容并在值中包含一个字符非常简单,只需使用 LEFT
和 CHARINDEX
:
LEFT(DS.Item,CHARINDEX('+',DS.Item + '+')-1)
你遇到的真实问题有点复杂:
- 你有一个非规范化的设计,使这变得更加困难。
- 您想在结果中保留非规范化设计,这又使这变得困难
- 您使用的 SQL 服务器版本非常 接近终止支持,内置没有支持字符串拆分和聚合。
也就是说,除非您使用的是 Azure SQL 数据库(或者以某种方式拥有 SQL Server 2022 的副本),否则我不建议 STRING_SPLIT
,因为它不提供序数位置参数。尽管 STRING_AGG
会使事情变得容易得多;你也可以使用 JSON 分离器。
相反,我在这里使用 DelimitedSplit8K_LEAD
,然后使用“Ye Olde FOR XML PATH
e (and STUFF
)”进行字符串聚合。这给出了这个笨拙的解决方案:
SELECT *
INTO dbo.YourTable
FROM (VALUES('095930'),
('CF0010+EN'),
('060983+PS'),
('086588+GG;086326+GG'),
('900010;'),
('CF0002;;CF0018;'))V(YourString);
GO
SELECT YT.YourString,
STUFF((SELECT ';' + LEFT(DS.Item,CHARINDEX('+',DS.Item + '+')-1)
FROM dbo.DelimitedSplit8K_LEAD(YT.YourString,';') DS
ORDER BY DS.ItemNumber
FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(8000)'),1,1,'') AS NewString
FROM dbo.YourTable YT;
GO
DROP TABLE dbo.YourTable;
如果您使用 Azure SQL 数据库(或 SQL Server 2022),那么答案会简单得多:
SELECT YT.YourString,
STRING_AGG(LEFT(SS.Value,CHARINDEX('+',SS.Value + '+')-1),';') WITHIN GROUP (ORDER BY SS.Ordinal) AS NewString
FROM dbo.YourTable YT
CROSS APPLY STRING_SPLIT(YT.YourString,';',1) SS
GROUP BY YT.YourString; --Assuming YourString has a unique value
编辑: 我犯了一个错误并回答了与 SSIS 相关的问题,并且回答时就好像您最初是在加载此数据一样。不过我要离开它,因为 SSIS 是 SQL 服务器的免费工具。
按照你的要求去做...
脚本组件:
var firstSplit = Row.[your Column].Split(';');
List<string> formatedCols = new List<string>();
foreach(var col in firstSplit)
formatedCols.Add(col.Split('+')[0]);
Row.[Output Column Name] = string.Join(";", formatedCols.ToArray());
我会推荐 child table 虽然与 parent 有一对多的关系。
我正在尝试过滤字符串的一部分直到它到达特定字符并重复直到字符串结束。
数据看起来像
095930
CF0010+EN
060983+PS
086588+GG;086326+GG
900010;
CF0002;;CF0018;
输出应该是
095930
CF0010
060983
086588;086326
900010;
CF0002;;CF0018;
我尝试了以下方法:
SUBSTRING(column, 1, CHARINDEX('+',column+ '+', 1)-1)
但这会删除 +
之后的所有内容,这不是我需要的。
删除后面的所有内容并在值中包含一个字符非常简单,只需使用 LEFT
和 CHARINDEX
:
LEFT(DS.Item,CHARINDEX('+',DS.Item + '+')-1)
你遇到的真实问题有点复杂:
- 你有一个非规范化的设计,使这变得更加困难。
- 您想在结果中保留非规范化设计,这又使这变得困难
- 您使用的 SQL 服务器版本非常 接近终止支持,内置没有支持字符串拆分和聚合。
也就是说,除非您使用的是 Azure SQL 数据库(或者以某种方式拥有 SQL Server 2022 的副本),否则我不建议 STRING_SPLIT
,因为它不提供序数位置参数。尽管 STRING_AGG
会使事情变得容易得多;你也可以使用 JSON 分离器。
相反,我在这里使用 DelimitedSplit8K_LEAD
,然后使用“Ye Olde FOR XML PATH
e (and STUFF
)”进行字符串聚合。这给出了这个笨拙的解决方案:
SELECT *
INTO dbo.YourTable
FROM (VALUES('095930'),
('CF0010+EN'),
('060983+PS'),
('086588+GG;086326+GG'),
('900010;'),
('CF0002;;CF0018;'))V(YourString);
GO
SELECT YT.YourString,
STUFF((SELECT ';' + LEFT(DS.Item,CHARINDEX('+',DS.Item + '+')-1)
FROM dbo.DelimitedSplit8K_LEAD(YT.YourString,';') DS
ORDER BY DS.ItemNumber
FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(8000)'),1,1,'') AS NewString
FROM dbo.YourTable YT;
GO
DROP TABLE dbo.YourTable;
如果您使用 Azure SQL 数据库(或 SQL Server 2022),那么答案会简单得多:
SELECT YT.YourString,
STRING_AGG(LEFT(SS.Value,CHARINDEX('+',SS.Value + '+')-1),';') WITHIN GROUP (ORDER BY SS.Ordinal) AS NewString
FROM dbo.YourTable YT
CROSS APPLY STRING_SPLIT(YT.YourString,';',1) SS
GROUP BY YT.YourString; --Assuming YourString has a unique value
编辑: 我犯了一个错误并回答了与 SSIS 相关的问题,并且回答时就好像您最初是在加载此数据一样。不过我要离开它,因为 SSIS 是 SQL 服务器的免费工具。
按照你的要求去做...
脚本组件:
var firstSplit = Row.[your Column].Split(';');
List<string> formatedCols = new List<string>();
foreach(var col in firstSplit)
formatedCols.Add(col.Split('+')[0]);
Row.[Output Column Name] = string.Join(";", formatedCols.ToArray());
我会推荐 child table 虽然与 parent 有一对多的关系。