我有一个逗号分隔的字符串,如下所示:
key1=value1,key2=value2,key3=value3,key1=value1.1,key2=value2.1,key3=value3.1
我想把它解析成一个看起来像这样的表:
Key1 Key2 Key3
==============================
value1 value2 value3
value1.1 value2.1 value3.1
我可以将字符串拆分为行:
ID Data
================
1 key1=value1
2 key2=value2
3 key3=value3
...
但是我被困在那里似乎无法找到办法完成剩下的工作。任何帮助表示赞赏。
答案 0 :(得分:0)
如果您能够将数据转换为每行格式的一个键/值对,那么大部分工作都已完成。让我称之为结果t
。这样的事情可能会让你完全接受:
select max(case when LEFT(data, 4) = 'key1' then SUBSTRING(data, 6, len(data)) end) as key1,
MAX(case when LEFT(data, 4) = 'key2' then SUBSTRING(data, 6, len(data)) end) as key2,
MAX(case when LEFT(data, 4) = 'key2' then SUBSTRING(data, 6, len(data)) end) as key3
from t
group by (id - 1)/3
这假定id
按顺序分配,如示例所示。
答案 1 :(得分:0)
这是一个更通用的版本,不依赖于顺序ID。但是,不清楚的是,最终结果中的value1
,value2
如何相互关联而不是value1
,value2.1
。在这个解决方案中,我任意对每个给定密钥的出现进行排序。
With SplitKeyValuePairs As
(
Select Id
, Left([Data], CharIndex('=', [Data]) - 1) As KeyName
, Substring([Data], CharIndex('=', [Data]) + 1, Len([Data])) As Value
, Row_Number() Over ( Partition By Left([Data], CharIndex('=', [Data]) - 1) Order By Id ) As RowNum
From SplitDelimitedString
)
Select Max ( Case When KeyName = 'Key1' Then Value End ) As [Key1]
, Max ( Case When KeyName = 'Key2' Then Value End ) As [Key2]
, Max ( Case When KeyName = 'Key3' Then Value End ) As [Key3]
From SplitKeyValuePairs
Group By RowNum
答案 2 :(得分:0)
这也应该有效:
SELECT *
FROM
(
SELECT
Grp = ID / 3,
KeyName = Left(Data, CharIndex('=', Data) - 1),
Value = Substring(Data, CharIndex('=', Data) + 1, 8000)
FROM
SplitString
) S
PIVOT (Max(Value) FOR KeyName IN (Key1, Key2, Key3)) P
答案 3 :(得分:0)
我知道这篇文章确实很老,但是请留在这里,以防万一有人觉得这对他们的特定解析要求有用或合适。
-- =============================================
-- Author: Peter Gumpal
-- Create date: October 23, 2018
-- Description: This function was developed to transform a key-value pair delimited string into a table.
--usage as follows:
-- Select * from dbo.KVParser('LP=pH FM=(begin)[odor](add)[odor](end) US=pgumpal')
-- this will return 3 records containing keys: LP, FM and US. Between "=" are values so if the string
-- used is a CSV, the comma character will not be omitted.
-- Key limitation: Fixed to two characters, update code as required.
-- Note: Code not optimal, suggestions/mods are always welcome. - Peter :)
-- =============================================
CREATE FUNCTION [dbo].[KVParser]
(
@pKVString varchar(500)
)
RETURNS @kvtemp table ([key] varchar(2), [val] varchar(300))
AS
Begin
Declare @str varchar(500)
set @str = @pKVString -- 'LP=pH FM=(begin)[odor](add)[odor](end) US=pgumpal'
Declare @curKey varchar(2)
Declare @curChar varchar(1)
Declare @concatStr varchar(300)
Declare @ctrI int
Set @ctrI = 0
While (len(@str) > @ctrI)
Begin
Set @curChar = SUBSTRING(@str,@ctrI,1)
If (@curChar = '=')
Begin
Set @curKey = SUBSTRING(@str, @ctrI - 2 ,2) --get the key
--begin, get value from its right side
Set @ctrI = @ctrI + 1
Set @curChar = SUBSTRING(@str,@ctrI,1)
Set @concatStr = ''
--loop into the value
While (@curChar <> '='AND len(@str) >= @ctrI)
Begin
Set @curChar = SUBSTRING(@str,@ctrI,1)
Set @concatStr = isnull(@concatStr,'') + ISNULL(@curChar,'')
Set @ctrI = @ctrI + 1
End
--end, get value from its right side
Insert into @kvtemp([key],[val])
Select @curKey, LEFT(@concatStr, IIF(RIGHT(@concatStr,1)= '=', len(@concatStr)-3,len(@concatStr)))
--above IIF was added to trim the closing key and = / line needs improvement.
Set @ctrI = @ctrI - 3 --decrement counter to 3 to back read the key for the closing =
End
Set @ctrI = @ctrI + 1
End
Return
End