我有一个带有“Payload”数据的列。它表示一个动态字段,其中应用程序将来自源(API,存储过程等)的所有数据提取到一个表中的一列中。每个有效负载可以是不同的列集,因此我无法将信息放入表中。但我需要我的团队能够提取信息。分隔符是静态的。 示例:源表如下所示
ID Payload
123 {"Transaction":"123456","Transaction2":"789123"}
124 {"Transaction":"123457","Transaction2":"789124"}
我希望最终输出为:
ID Transaction Transaction2
123 123456 789123
124 123457 789124
我有一个分割功能,我可以通过两次来获取以下内容:
ID SplitID Split SplitID2 Split 2
123 1 transaction:123456 1 transaction
123 1 transaction:123456 2 123456
123 2 transaction2:789123 1 transaction2
123 2 transaction2:789123 2 789123
124 1...
所以现在我需要在不使用动态SQL的情况下展平它...或者将它放在一个20人的团队可以使用和定期使用的地方,没有持久的表等......
编辑:我们目前有SQL 2012.我们距离2017年还有几个月。抱歉没有记录。
答案 0 :(得分:2)
如果您有SQL Server 2016,则可以使用json_value
:
select id
, json_value(payload, '$.Transaction')
, json_value(payload, '$.Transaction2')
from t1
对于早期版本的SQL Server,您需要一个CLR UDF,例如JSON Select。
答案 1 :(得分:2)
我感觉你不在2016 +
SQL Server是按设计声明的,因此无法获得变量列而不会变为动态。
如果您有最大列数,请考虑以下事项:
示例强>
Select A.ID
,C.*
From YourTable A
Cross Apply (Select CleanString = replace(replace(replace(replace(Payload,'{',''),',',':'),'"',''),'}','') ) B
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
,Pos4 = ltrim(rtrim(xDim.value('/x[8]','varchar(max)')))
,Pos5 = ltrim(rtrim(xDim.value('/x[10]','varchar(max)')))
,Pos6 = ltrim(rtrim(xDim.value('/x[12]','varchar(max)')))
,Pos7 = ltrim(rtrim(xDim.value('/x[14]','varchar(max)')))
,Pos8 = ltrim(rtrim(xDim.value('/x[16]','varchar(max)')))
,Pos9 = ltrim(rtrim(xDim.value('/x[18]','varchar(max)')))
From (Select Cast('<x>' + replace(CleanString,':','</x><x>')+'</x>' as xml) as xDim) as A
) C
<强>返回强>
ID Pos1 Pos2 Pos3 Pos4 Pos5 Pos6 Pos7 Pos8 Pos9
123 123456 789123 NULL NULL NULL NULL NULL NULL NULL
124 123457 789124 NULL NULL NULL NULL NULL NULL NULL
答案 2 :(得分:1)
如果该文档对于JSON稍微更精细,并且您运行SQL Server 2016 + ..:
DECLARE @json NVARCHAR(MAX)
SET @json =
N'[
{"ID" : "123", "Payload" : {"Transaction":"123456","Transaction2":"789123"}},
{"ID" : 124, "Payload" : {"Transaction":"123457","Transaction2":"789124"}}
]'
SELECT *
FROM OPENJSON(@json)
WITH (id int '$.ID',
Transaction1 int '$.Payload.Transaction',
Transaction2 int '$.Payload.Transaction2'
)
答案 3 :(得分:1)
如果您没有SQL Server 2016或更高版本,那么答案会更复杂一些。我要做的是在第一次拆分后停止(不要将名称和值拆分成单独的行),所以你的表看起来像:
ID SplitID Split
123 1 transaction:123456
123 2 transaction2:789123
124 1...
...一个事务/行,一行/事务。假设拆分确实删除了引号,如下所示,那么类似下面的内容应该可以工作(未经测试):
select id
, Transaction
, Transaction2
FROM
(SELECT LEFT(Split, CHARINDEX(':', Split)-1) AS FieldName
SUBSTRING(Split, CHARINDEX(':', Split)+1,999) AS FieldValue
FROM udf.splittable(t1)) as sourcetable
PIVOT
(
MIN(FieldValue)
FOR FieldName IN ([Transaction], [Transaction2])
) AS PivotTable;
...但是,如果你有2016年或更高,请使用其他答案中提到的JSON路线。 :)
答案 4 :(得分:0)
如果您可以尝试RegexAssembly
{{1}}