【问题标题】:Result order of string_split?string_split 的结果顺序?
【发布时间】:2020-02-08 18:18:33
【问题描述】:

现在我发现了这个很棒的string_split() 函数,然后我了解到输出行可能是任意顺序的。不保证顺序与输入字符串中子字符串的顺序一致。。这使得该功能对我来说毫无用处。

是否有解决方法?

编辑 - 示例:

SELECT value FROM String_Split('b,a,c', ',')

在这种情况下,我希望这个结果按以下顺序:

value
------
b
a
c

但是,根据 Microsoft 的说法,此订单不保证。那么我怎样才能得到这个结果呢?

【问题讨论】:

  • 这可能会有所帮助stackoverflow.com/a/59749515/10532500
  • “那么我怎样才能得到这个结果呢?” 通过使用提供序数位置的解决方案; STRING_SPLIT 没有。自从在 SQL Server 2016 中引入以来,人们一直抱怨缺乏此信息,MS 似乎不想将其添加到该功能中。例如,我建议查找DelimitedSplit8K_LEAD
  • 'a' 是“小于”'b', @SurajKumar ,该答案假定序数位置和值顺序相同。

标签: sql-server split azure-sql-database sql-server-2016 sql-server-2017


【解决方案1】:

您可以尝试使用基于 JSON 的方法。您需要将输入字符串转换为有效的 JSON 数组(b,a,c 转换为 ["b","a","c"]),然后使用 OPENJSON() 和默认模式解析此数组。结果是一个包含 keyvaluetype 列的表,根据文档,key 列是一个 nvarchar(4000) 值,其中包含指定属性的名称或指定数组中元素的索引.

声明:

DECLARE @StringToSplit VARCHAR(100) = 'b,a,c';

SELECT [value]
FROM OPENJSON(CONCAT('["', REPLACE(@StringToSplit, ',', '","'), '"]'))
ORDER BY CONVERT(int, [key])

结果:

value
b
a
c

如果输入字符串中有引号,请尝试使用以下语句,使用STRING_ESCAPE()

DECLARE @StringToSplit VARCHAR(100) = '"b",''a'',c';

SELECT [value]
FROM OPENJSON(CONCAT('["', REPLACE(STRING_ESCAPE(@StringToSplit, 'json'), ',', '","'), '"]'))
ORDER BY CONVERT(int, [key])

结果:

value
"b"
'a'
c

【讨论】:

  • 非常感谢,这是一个很好的解决方案!只是为了完整:如果原始字符串包含引号,那么它们必须被转义?
  • 哇,谢谢,太棒了!现在了解到,对于像 json 这样的特殊类型,有一个转义函数!
  • @askolotl 是,但目前STRING_ESCAPE() 仅支持 JSON。
  • 这种保证顺序的 JSON 方法是什么?我不相信它会。
  • @wBob 它位于documentation - 当您使用默认模式调用 OPENJSON 时,...该函数返回一个包含以下列的表:a) 键。一个 nvarchar(4000) 值,其中包含指定属性的名称或指定数组中元素的索引。键列具有 BIN2 排序规则,....
【解决方案2】:

如果您要拆分的字符串中没有重复项,则可以使用以下内容。

DECLARE @StringToSplit VARCHAR(100) = 'b,a,c';

SELECT  
    value 
FROM String_Split(@StringToSplit, ',') d
ORDER BY CHARINDEX(','+  value+ ',',  ',' + @StringToSplit + ',' )

【讨论】:

  • 有趣的答案,但我有重复。
  • @askolotl - 你运气不好,应该寻找另一个字符串拆分器而不是String_Split,直到它添加了这个缺失的功能
  • @SurajKumar - 没有人说 ORDER BY 不能与 String_Split 一起使用 - 缺少的功能是一个索引列,说明找到拆分项的顺序。理想情况下,该函数将返回与SELECT * FROM (VALUES ('b',1),('a',2),('c',3)) V(value, idx) 相同的结果集,然后我们可以按idx 排序
  • @SurajKumar 正是马丁所说的。 split_string 函数只返回值,但它不会告诉您在哪个位置找到了字符串。结果中缺少一个索引列。
  • 如果有重复,可以使用Ronen Ariely describes here的方法。但是请注意,由于性能问题,他本人并不推荐这种方法。使用内置函数以外的其他东西可能会更好。
【解决方案3】:
 <!-- language: lang-sql --> 
SELECT p.[Id], [p].[Body], [x].[value], x.[RN]
FROM [dbo].[Posts] AS [p]
CROSS APPLY (
SELECT ss.[value], 
     ROW_NUMBER() OVER (PARTITION BY [p].[Id] ORDER BY [p].[Id]) AS RN <--------- (SORT)
FROM STRING_SPLIT([p].[Body], ' ') AS [ss]
      ) AS x

【讨论】:

  • 能否请您格式化代码并解释背后的逻辑?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
相关资源
最近更新 更多