【问题标题】:String split or other similar SQL Server functions with case statement带有 case 语句的字符串拆分或其他类似的 SQL Server 函数
【发布时间】:2018-08-22 11:07:56
【问题描述】:

我已准备好this demo,我想在 SQL Server 中使用 string_split 或其他函数,可能在 case 语句中实现如下输出:

Writer   
Sabao Fulano, Sapato Feio, Jose Perreira
Toze Jose
Feijao Mauricio

编辑

这个问题与 cmets 中建议的问题之间的区别在于,这里不仅有要拆分的逗号,而且每个名称都以这种方式附带一个“XX”:

  1. “萨宝富拉诺,XX Some_Random_Text”变成“萨宝富拉诺”

  2. “Sapato Feio, XX, Jose Perreira, XX”改为“Sapato Feio, Jose Perreira”

基本上,如果XX旁边没有逗号,那么只留下第一个实例,说“Sabao Fulano”,或者如果有XX +“,” 然后删除它们中的两个(上面的第二种情况)。这个想法是只留下用逗号分隔的名称。

【问题讨论】:

  • 我不听你的问题。如果您的输出是 CSV 数据,那么为什么会涉及 STRING_SPLIT?顺便说一句,将 CSV 数据存储在 SQL 表中通常是个坏主意。如果你发现自己经常使用STRING_SPLIT,这可能意味着糟糕的表格设计。
  • T-SQL split string的可能重复
  • STRING_SPLIT 是一个表函数,而不是一个标量函数。您不能在 CASE 表达式(不是语句)中使用它。我真的不明白你在这里的目标是什么。
  • 我们的目标是只有名字而不是 XX。所以 XX 应该被过滤掉。
  • @Larnu 在 CASE 语句中使用 STRING_SPLIT 或表函数没有限制。我不确定这句话“You can't use it within a CASE expression”是什么意思。澄清一下,这里是简单的代码:select CASE WHEN (SELECT COUNT(*) FROM STRING_SPLIT('a,b',',') t) > 1 then 1 ELSE 0 END。我很确定这不是你的意思;-)

标签: sql-server replace split


【解决方案1】:

早安,

要求并不完全清楚,因为您在描述中说“The goal is to have just names and not XX.”,但在请求的结果中,您没有源中存在的文本“Article 3”。

如果您只是想删除“,XX”,那么我们可以使用简单的REPLACE,如下所示:

WITH WriterTbl AS (
    SELECT 'Sabao Fulano, XX, Sapato Feio, XX, Jose Perreira, XX' AS Writer UNION ALL
    SELECT 'Toze Jose, XX' UNION ALL
    SELECT 'Feijao Mauricio, XX Article 3'
)
select REPLACE(WriterTbl.Writer,', XX',', ')
from WriterTbl

但是如果你真的想删除以“,XX”开头的部分并且你要求使用STRING_SPLIT,就像你在原始问题中提出的那样(假设你不会改变问题),那么我们可以使用STRING_SPLIT来查找我们需要删除的文本部分,然后我们可以使用函数 STRING_AGG 再次连接文本

有一点你必须记住,我很确定大多数人都没有想到:STRING_SPLIT 不保证结果的顺序,这意味着通过拆分文本并重新连接它,你可能会得到不同的顺序

根据这些限制和您的要求,请检查此解决方案:

WITH WriterTbl AS (
    SELECT 'Sabao Fulano, XX, Sapato Feio, XX, Jose Perreira, XX' AS Writer UNION ALL
    SELECT 'Toze Jose, XX' UNION ALL
    SELECT 'Feijao Mauricio, XX Article 3'
),
MyCTE AS(
    select MyGroup = ROW_NUMBER() OVER (order by (select null)), t1.Writer
    from WriterTbl t1
)
SELECT STRING_AGG(t2.[value], ',') 
FROM MyCTE t1
CROSS APPLY (
    SELECT * from STRING_SPLIT (t1.Writer, ',') t2
) t2
where not t2.[value] like ' XX%'
group by MyGroup

注意!不建议执行此任务,我强烈建议您重新考虑您的要求和架构!

Sub-Note! 即使您仍然需要从此输入中获取此结果,您也应该创建自己的函数,而不是使用内置函数 STRING_SPLIT。没有理由拆分数据以将其连接回来。在您的用户函数中,您可以简单地删除以“,XX”开头并以“,”结尾的文本,或者如果这是值的最后一部分。这里的解决方案是根据您的要求使用 STRING_SPLIT

【讨论】:

  • 谢谢。第二个查询按要求工作。解说也很棒。谢谢!在这里测试:sqlfiddle.com/#!18/9eecb/30939
  • 不客气@feijao。我很高兴能帮上一点忙。周末愉快
【解决方案2】:

试试这个查询:

select case when lastComma < firstXX then substring(writer, 1, lastComma - 1)
            else replace(replace(writer, 'XX', ''), ', ,',',') end
from (
    select *,
           charindex('XX', writer) firstXX,
           len(writer) - charindex(',', reverse(writer)) + 1 lastComma
    from WriterTbl
) a

基于逗号的最后一个索引和XX 的第一次出现,在外部查询中决定是要删除最后一个条目还是只替换XX(另外我添加了将双逗号替换为一个)。

【讨论】:

  • 嗨 Michał,(1) 据我所知(我希望我弄错了),OP 的基本要求是使用 string_split "I would like to use string_split"。例如,这可能是与学校相关的要求,在这种情况下,即使这不是最佳解决方案(正如我在回答中所写),我们也需要遵循。 (2) 您的解决方案需要对此输入进行一些调整:"'a, XX, b, XX, c, XX'"(最后返回逗号)。或者对于这个输入:“'a, XX b c, XX, d'”(返回“b c”),等等......
  • 无法运行它。但我认为@RonenAriely 的回答是可以接受的。感谢您的努力和时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 2015-03-17
  • 1970-01-01
  • 2020-05-09
  • 2013-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多