[英]SQL query from XML Column stored as nvarchar
我需要 sql 查詢方面的幫助。 我有一個帶有列的表,其中 xml 存儲為 nvarchar。
Xml曲線 |
---|
<?xml version="1.0" encoding="Windows-1252"?> |
所有 XML 看起來像:
<?xml version="1.0" encoding="Windows-1252"?>
<Curve xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Anchor>Begin</Anchor>
<LoadOnlyNOKCurves>false</LoadOnlyNOKCurves>
<Teachmode>false</Teachmode>
<ActualCurve>
<FloatPoints>0;4.965425|0.01004791;5.438642|0.01076508;5.50529|0.01112366;5.485298</FloatPoints>
</ActualCurve>
<AbsOffset>
<X>88.21842</X>
<Y>0</Y>
</AbsOffset>
<UpperLimit>
<FloatPoints>9.456265E-05;5.023251|0.008893617;5.502031</FloatPoints>
</UpperLimit>
<LowerLimit>
<FloatPoints>0.0008510638;4.906321|0.01408511;5.495711</FloatPoints>
</LowerLimit>
<ULViolationCurveIdx>-1</ULViolationCurveIdx>
<ULViolationULIdx>-1</ULViolationULIdx>
<LLViolationCurveIdx>-1</LLViolationCurveIdx>
<LLViolationLLIdx>-1</LLViolationLLIdx>
<SIO_X>
<Id>1</Id>
<Alias>Position</Alias>
<Unit>mm</Unit>
</SIO_X>
<SIO_Y>
<Id>2</Id>
<Alias>Force</Alias>
<Unit>kN</Unit>
</SIO_Y>
</Curve>
And i need built SQL query, which select data in first tag FloatPoints: <FloatPoints>0;4.965425|0.01004791;5.438642|0.01076508;5.50529|0.01112366;5.485298</Floatpoint>
解釋:
<FloatPoints>x1;y1|x2;y2|x3;y3|x4;y4</FloatPoints>
因此,我想要這個結果:
x1 | y1 | x2 | y2 | x3 | y3 | x4 | y4 |
---|---|---|---|---|---|---|---|
0 | 4.965425 | 0.01004791 | 5.438642 | 0.01076508 | 5.50529 | 0.01112366 | 5.485298 |
如果可能的話。
這個答案有幾個假設:
xml
值。ActualCurve
中想要的值TRANSLATE
的版本(如果沒有,請使用嵌套的REPLACE
s)有了這個假設,您可以執行以下操作:
nvarchar
轉換為有效的xml
值Curve/ActualCurve/FloatPoints
的值PARSENAME
將單獨的部分分隔為CHARINDEX
獲取字符串的正確左/右部分CONVERT
回float
DECLARE @XMLLikeString nvarchar(MAX) = '<?xml version="1.0" encoding="Windows-1252"?>
<Curve xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Anchor>Begin</Anchor>
<LoadOnlyNOKCurves>false</LoadOnlyNOKCurves>
<Teachmode>false</Teachmode>
<ActualCurve>
<FloatPoints>0;4.965425|0.01004791;5.438642|0.01076508;5.50529|0.01112366;5.485298</FloatPoints>
</ActualCurve>
<AbsOffset>
<X>88.21842</X>
<Y>0</Y>
</AbsOffset>
<UpperLimit>
<FloatPoints>9.456265E-05;5.023251|0.008893617;5.502031</FloatPoints>
</UpperLimit>
<LowerLimit>
<FloatPoints>0.0008510638;4.906321|0.01408511;5.495711</FloatPoints>
</LowerLimit>
<ULViolationCurveIdx>-1</ULViolationCurveIdx>
<ULViolationULIdx>-1</ULViolationULIdx>
<LLViolationCurveIdx>-1</LLViolationCurveIdx>
<LLViolationLLIdx>-1</LLViolationLLIdx>
<SIO_X>
<Id>1</Id>
<Alias>Position</Alias>
<Unit>mm</Unit>
</SIO_X>
<SIO_Y>
<Id>2</Id>
<Alias>Force</Alias>
<Unit>kN</Unit>
</SIO_Y>
</Curve>';
SELECT CONVERT(float,LEFT(xy1,CHARINDEX(';',xy1)-1)) AS x1,
CONVERT(float,STUFF(xy1,1,CHARINDEX(';',xy1),'')) AS y1,
CONVERT(float,LEFT(xy2,CHARINDEX(';',xy2)-1)) AS x2,
CONVERT(float,STUFF(xy2,1,CHARINDEX(';',xy2),'')) AS y2,
CONVERT(float,LEFT(xy3,CHARINDEX(';',xy3)-1)) AS x3,
CONVERT(float,STUFF(xy3,1,CHARINDEX(';',xy3),'')) AS y3,
CONVERT(float,LEFT(xy4,CHARINDEX(';',xy4)-1)) AS x4,
CONVERT(float,STUFF(xy4,1,CHARINDEX(';',xy4),'')) AS y4
FROM (VALUES(@XMLLikeString))V(XMLLikeString)
CROSS APPLY (VALUES(TRY_CONVERT(xml,CONVERT(varchar(MAX),V.XMLLikeString))))TC(XML)
CROSS APPLY (VALUES(TC.XML.value('(Curve/ActualCurve/FloatPoints/text())[1]','varchar(4000)')))AC(FloatPoints)
CROSS APPLY (VALUES(TRANSLATE(AC.FloatPoints,'.|',',.')))T(FloatPoints)
CROSS APPLY (VALUES(REPLACE(PARSENAME(T.FloatPoints,4),',','.'),REPLACE(PARSENAME(T.FloatPoints,3),',','.'),REPLACE(PARSENAME(T.FloatPoints,2),',','.'),REPLACE(PARSENAME(T.FloatPoints,1),',','.')))PN(xy1,xy2,xy3,xy4);
撇開編碼不談,問題是在解析 FloatPoints 標記時保留項目位置。 不幸的是, string_split
不能保證保留項目位置,因此您可能需要一個自定義拆分器(此處為DelimitedSplit8K_LEAD
),它也返回項目 position。
select id,
Max(case t2.itemnumber*100 + t3.itemnumber when 101 then cast(t3.Item as decimal(10,6)) end) x1,
Max(case t2.itemnumber*100 + t3.itemnumber when 102 then cast(t3.Item as decimal(10,6)) end) y1,
Max(case t2.itemnumber*100 + t3.itemnumber when 201 then cast(t3.Item as decimal(10,6)) end) x2,
Max(case t2.itemnumber*100 + t3.itemnumber when 202 then cast(t3.Item as decimal(10,6)) end) y2
...
from (select id, cast(txn_message as xml) x
from tbl) a
cross apply a.x.nodes('Curve/ActualCurve/FloatPoints') t(n)
cross apply DelimitedSplit8K_LEAD(t.n.value('.[1]', 'varchar(200)') , '|') t2
cross apply DelimitedSplit8K_LEAD(t2.Item, ';') t3
group by id;
包括DelimitedSplit8K_LEAD
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.