2016-11-10 8 views
1

SQL Serverで文字列として格納された複雑なJSONオブジェクトを解析する最善の方法を理解しようとしています。SQL Serverで複雑な文字列を解析する方法

私のテーブルには、次の情報を持っています

LogID  | Content 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
55271413 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218912","CarrierScac":"XYZ","Latitude":33.595555,"Longitude":-85.854722,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 
55271414 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218944","CarrierScac":"XYZ","Latitude":37.996666,"Longitude":-78.314444,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 
55271415 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219079","CarrierScac":"YZB","Latitude":34.027500,"Longitude":-117.522222,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 
55271416 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219020","CarrierScac":"XYZ","Latitude":37.754722,"Longitude":-121.144166,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 
55271417 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218911","CarrierScac":"XYZ","Latitude":40.585833,"Longitude":-91.425000,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 
55271418 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218785","CarrierScac":"XYZ","Latitude":30.747500,"Longitude":-85.270277,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 
55271426 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219044","CarrierScac":"XYZ","Latitude":33.598333,"Longitude":-97.936388,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""} 

私は、各文字列を解析し、列名としてJSON属性の名前で新しい列内に配置しようとすると、対応する値よ行の値

例えば、ここで私は行ごとに以下を探していた結果、次のようになります。

LogID  | LicensePlate | FreightHaulerProviderXId | FreightProviderReferenceNumber | CarrierScac | Latitude | Longitude | StreetAddress1 | StreetAddress2 | City | State | PostalCode | Country 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
55271413 |    | ABC      | 5218912       | XYZ   | 33.595555 | -85.854722 |     |     |  |   |    |     

私はいくつかのおそらくかなり悪いSQLロジックを使用して、それを解析しようとしました。基本的には、文字列全体を探し、サブストリングをつかんで、列名を手動で割り当てます。これはスケーラビリティとパフォーマンスのための非常に良い解決策ではありません。

SELECT DISTINCT 
    SUBSTRING(lcon.Content, CHARINDEX('CarrierScac', lcon.Content)+14, CHARINDEX('City',lcon.Content) - CHARINDEX('CarrierScac', lcon.Content) + Len('City')-21) as 'CarrierScac', 
    SUBSTRING(lcon.Content, CHARINDEX('Latitude', lcon.Content)+10, CHARINDEX('Longitude',lcon.Content) - CHARINDEX('Latitude', lcon.Content) + Len('Longitude')-21) as 'Latitude', 
    SUBSTRING(lcon.Content, CHARINDEX('Longitude', lcon.Content)+11, CHARINDEX('PositionEventType',lcon.Content) - CHARINDEX('Longitude', lcon.Content) + Len('"PositionEventType')-31) as 'Longitude' 
FROM 
    acg.LogContext lcon 
WHERE 
    lcon.Content LIKE '%XYZ%' 

私は一日のうちに良い半分のテクニックを研究しても完全に困惑しているようです。

ありがとうございます!

+2

を必要に応じて、JSONサポートがデータベースに組み込まれています:https://msdn.microsoft.com/en-us/library/dn921897.aspx。 –

答えて

6

と2つのクロスが適用され

Declare @YourTable table (LogID int,Content varchar(max)) 
Insert Into @YourTable values 
(55271413,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218912","CarrierScac":"XYZ","Latitude":33.595555,"Longitude":-85.854722,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'), 
(55271414,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218944","CarrierScac":"XYZ","Latitude":37.996666,"Longitude":-78.314444,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'), 
(55271415,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219079","CarrierScac":"YZB","Latitude":34.027500,"Longitude":-117.522222,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'), 
(55271416,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219020","CarrierScac":"XYZ","Latitude":37.754722,"Longitude":-121.144166,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'), 
(55271417,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218911","CarrierScac":"XYZ","Latitude":40.585833,"Longitude":-91.425000,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'), 
(55271418,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218785","CarrierScac":"XYZ","Latitude":30.747500,"Longitude":-85.270277,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'), 
(55271426,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219044","CarrierScac":"XYZ","Latitude":33.598333,"Longitude":-97.936388,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}') 


Select LogID 
     ,LicensePlate = max(case when Item='LicensePlate' then Value else null end) 
     ,FreightHaulerProviderXId = max(case when Item='FreightHaulerProviderXId' then Value else null end) 
     ,FreightProviderReferenceNumber = max(case when Item='FreightProviderReferenceNumber' then Value else null end) 
     ,CarrierScac = max(case when Item='CarrierScac' then Value else null end) 
     ,Latitude = max(case when Item='Latitude' then Value else null end) 
     ,Longitude = max(case when Item='Longitude' then Value else null end) 
     ,StreetAddress1 = max(case when Item='StreetAddress1' then Value else null end) 
     ,StreetAddress2 = max(case when Item='StreetAddress2' then Value else null end) 
     ,City = max(case when Item='City' then Value else null end) 
     ,State = max(case when Item='State' then Value else null end) 
     ,PostalCode = max(case when Item='PostalCode' then Value else null end) 
     ,Country = max(case when Item='Country' then Value else null end) 
From ( 
     Select LogID 
       ,Item = max(case when RetSeq=1 then RetVal else null end) 
       ,Value = max(case when RetSeq=2 then RetVal else null end) 
     From (
       Select A.LogID 
         ,Grp = B.RetSeq 
         ,C.* 
       From @YourTable A 
       Cross Apply (Select RetSeq,RetVal=Replace(Replace(Replace(RetVal,'"',''),'{',''),'}','') From [dbo].[udf-Str-Parse](A.Content,',')) B 
       Cross Apply (Select * From [dbo].[udf-Str-Parse](B.RetVal,':')) C 
      ) N Group By LogID,Grp 
    ) F 
Group By LogID 

戻り

:とにかく、ここで ソリューションの誰かがでアップ来ています

enter image description here


UDFのSQL Server 2016以降で

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10)) 
Returns Table 
As 
Return ( 
    Select RetSeq = Row_Number() over (Order By (Select null)) 
      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
    From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i) 
); 
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
+0

あなたはGENIUSです。 – colonelsanders91

+1

@ colonelsanders91天才...私の妻は同意しないでしょう。「やって学ぶ」ことだけを勧めて、大金打者を見て、毎日何かを学びます。 –

0

1つの選択肢はSQL Server 2016にアップグレードすることです。それ以外の場合は、SQL CLR統合でNewtonsoftライブラリを使用することを検討します。

http://www.newtonsoft.com/json

+0

膨大な数のソースがあり、SQL CLRがどのようにメモリリークを起こしているかを詳しく説明しています。これは解決されましたか? –

+0

残念ながら私は2016年にアップグレードすることはできませんし、私たちのデータベースへのサードパーティ製の統合にもパーマはありません:( – colonelsanders91

0

JSON ... CLRは、ほとんどの人に好まれているように思えます。ここでは面白いTSQLのアプローチです。

私はここにちょうどリンクを投稿することは丁寧ではないことを知っていますが、これはほとんどの人にとってはTLです; @Gordon Linoffが言及しているように、2016には組み込みのサポートがあります。 ... parse関数の助けを借りて

​​

関連する問題