将 split_string 中的行转置为列

Transpose rows from split_string into columns

我无法尝试将一组行转置为 table。在我的存储过程中,我将带分隔符的字符串作为输入,并需要转置它。

SELECT * 
FROM string_split('123,4,1,0,0,5|324,2,0,0,0,4','|')
CROSS APPLY  string_split(value,',')

我从中收到:

value           value
123,4,1,0,0,5   123
123,4,1,0,0,5   4
123,4,1,0,0,5   1
123,4,1,0,0,5   0
123,4,1,0,0,5   0
123,4,1,0,0,5   5
324,2,0,0,0,4   324
324,2,0,0,0,4   2
324,2,0,0,0,4   0
324,2,0,0,0,4   0
324,2,0,0,0,4   0
324,2,0,0,0,4   4

|分隔的值是客户详细信息。在每个客户端中,有六个属性,由 , 分隔。我想要 table 的输出:

ClientId ClientTypeId AttrA AttrB AttrC AttrD
------------------------------------------------
123      4            0     0     0     5
324      2            0     0     0     4

解决此问题的最佳方法是什么?我一直在查看 PIVOT 但无法使其正常工作,因为看起来我至少需要行号。

此答案假定行号函数将 "follow the order" 字符串。如果没有,您将需要编写自己的拆分,在结果 table 中包含一个行号。 (这是在官方文档页面上询问的,但没有给出官方答案)。

SELECT
  MAX(CASE WHEN col = 1 THEN item ELSE null END) as ClientId,
  MAX(CASE WHEN col = 2 THEN item ELSE null END) as ClientTypeId,
  MAX(CASE WHEN col = 3 THEN item ELSE null END) as AttrA,
  MAX(CASE WHEN col = 4 THEN item ELSE null END) as AttrB,
  MAX(CASE WHEN col = 5 THEN item ELSE null END) as AttrC,
  MAX(CASE WHEN col = 6 THEN item ELSE null END) as AttrD
FROM (
  SELECT A.value as org, B.value as item, 
         ROW_NUMBER() OVER (partition by A.value) as col 
  FROM string_split('123,4,1,0,0,5|324,2,0,0,0,4','|') as A
  CROSS APPLY  string_split(A.value,',') as B
) X
GROUP BY org

您可能会收到有关忽略聚合函数中的空值的消息。 (我总是忘记哪些平台关心哪些平台不关心。)如果你这样做,你可以用 0 替换 null。

Note, this is not as fast and using a CTE to find the 5 commas in the string with CHARINDEX and then using SUBSTRING to extract the values. But I'm to lazy to write up that solution which I would need to test to get all the off by 1 issues right. Still, I suggest you do it that way if you have a big data set.

我知道你已经得到了相当多的答案,但在这里你可以找到一个 PIVOT 解决方案

select [ClientID],[ClientTypeId],[AttrA],[AttrB],[AttrC],[AttrD]
FROM 
(
select case when ColumnRow = 1 then 'ClientID'
        when ColumnRow = 2 then 'ClientTypeId'
        when ColumnRow = 3 then 'AttrA'
        when ColumnRow = 4 then 'AttrB'
        when ColumnRow = 5 then 'AttrC'
        when ColumnRow = 6 then 'AttrD'   else null end as 
 ColumnRow,t.value,ColumnID from (

 select ColumnID,z.value as stringsplit,b.value,  cast(Row_number() 
 over(partition by z.value order by z.value) as 
 varchar(50)) as ColumnRow from (SELECT cast(Row_number() over(order by 
 a.value) as 
 varchar(50)) as ColumnID,
 a.value

 FROM string_split('123,4,1,0,0,5|324,2,0,0,0,4','|') a
 )z  
 CROSS APPLY  string_split(value,',') b
 )t

 ) AS SOURCETABLE
 PIVOT
 (
 MAX(value)
 FOR ColumnRow IN ([ClientID],[ClientTypeId],[AttrA],[AttrB],[AttrC],
 [AttrD])
 )
 AS
 PivotTable