将单个列解析为多个

时间:2018-03-28 18:12:43

标签: sql sql-server parsing

我有一个带有“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年还有几个月。抱歉没有记录。

5 个答案:

答案 0 :(得分:2)

如果您有SQL Server 2016,则可以使用json_value

select  id
,       json_value(payload, '$.Transaction')
,       json_value(payload, '$.Transaction2')
from    t1

Example at SQL Fiddle.

对于早期版本的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}}