SQL 交叉应用没有结果
SQL Cross Apply no results
我有 丑 XML 看起来像这样:
<?xml version="1.0"?>
<MainTag xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RecordID="201801026543210">
<Field Name="TheFieldName">
<FieldValue>Field Contents</FieldValue>
<ListTag>
<ListItem>
<Value>This List Value</Value>
<Source>source.txt</Source>
<ListType>text</ListType>
<ItemNumber>6912</ItemNumber>
<MoreData>some text here</MoreData>
<Address>address data</Address>
<Ranking>102</Ranking>
</ListItem>
<ListItem>
<Value>Another List Value</Value>
<Source>other.txt</Source>
<ListType>text</ListType>
<ItemNumber>7919</ItemNumber>
<MoreData>more text here</MoreData>
<Address>address data</Address>
<Ranking>41</Ranking>
</ListItem>
</ListTag>
</Field>
</MainTag>
我想要的是给我一个电子表格的查询结果,本质上是:
RecordID FieldName FieldValue ListValue ListSource ListType ListItemNumber …
201801026543210 TheFieldName Field Contents This List Value source.txt text 6912
201801026543210 TheFieldName Field Contents Another List Value other.txt text 7919
为了增加乐趣,XML 存储在 varchar 字段中,而不是 XML 字段。
作为我尝试过的示例数据和查询:
DECLARE @Tbl TABLE (
TblID varchar(15)
, Fld varchar(max)
)
INSERT INTO @Tbl SELECT '201801026543210', '<?xml version="1.0"?><MainTag xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RecordID="201801026543210"><Field Name="TheFieldName"><FieldValue>Field Contents</FieldValue><ListTag><ListItem><Value>This List Value</Value><Source>source.txt</Source><ListType>text</ListType><ItemNumber>6912</ItemNumber><MoreData>some text here</MoreData><Address>address data</Address><Ranking>102</Ranking></ListItem><ListItem><Value>Another List Value</Value><Source>other.txt</Source><ListType>text</ListType><ItemNumber>7919</ItemNumber><MoreData>more text here</MoreData><Address>address data</Address><Ranking>41</Ranking></ListItem></ListTag></Field></MainTag>'
-- this shows that i am reading the main tag
SELECT t.r.value('@RecordID','varchar(15)') AS RecordID
, t.r.query('.') as fullvalue
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
-- and this works to read the attribute from the first field
SELECT t.r.value('@RecordID', 'varchar(18)') AS RecordID
, f.r.value('@Name', 'varchar(100)') AS Field
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
CROSS APPLY Fld.nodes('/MainTag/Field') AS f(r)
-- this does NOT work to read the second field
SELECT t.r.value('@RecordID','varchar(18)') AS RecordID
, f.r.value('.', 'varchar(100)') AS ValueF
, p.r.query('.') AS QueryP
, p.r.value('.', 'varchar(100)') AS ValueP
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
CROSS APPLY Fld.nodes('/MainTag/Field') AS f(r)
CROSS APPLY Fld.nodes('/MainTag/FieldValue') AS p(r)
-- i honestly feel like this should be using nodes off of the parent nodes method
-- , but this is NOT working either
SELECT t.r.value('@RecordID','varchar(18)') AS RecordID
, p.r.query('.') AS FieldValue
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY s.Fld.nodes('/MainTag') AS t(r)
CROSS APPLY t.r.nodes('/MainTag/FieldValue') AS p(r)
我看到其他一些 questions/samples 只抓取第一个条目。我不要那个。我想要一大块数据。我希望每个 "ListItem" 重复唯一字段。换句话说:我知道这类似于一对多联接,其中 "one" table 中的字段将针对 "many" [=35= 中的每一行重复].
从技术上讲,在我的数据中可能还有不止一个 "Field"。
该字段只有一个 FieldValue。
存在一个或多个 ListItem。
用这个查询试试:
SELECT s.Fld.value('(/MainTag/@RecordID)[1]','bigint') AS RecordID
,A.f.value('@Name','nvarchar(max)') as FieldName
,A.f.value('(FieldValue/text())[1]','nvarchar(max)') as FieldValue
,B.li.value('(Value/text())[1]','nvarchar(max)') as ListValue
,B.li.value('(Source/text())[1]','nvarchar(max)') as ListSource
--and so on
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag/Field') AS A(f)
CROSS APPLY A.f.nodes('ListTag/ListItem') AS B(li)
提示
如果有任何机会将存储从 VARCHAR
更改为 XML
,那是值得的...
我有 丑 XML 看起来像这样:
<?xml version="1.0"?>
<MainTag xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RecordID="201801026543210">
<Field Name="TheFieldName">
<FieldValue>Field Contents</FieldValue>
<ListTag>
<ListItem>
<Value>This List Value</Value>
<Source>source.txt</Source>
<ListType>text</ListType>
<ItemNumber>6912</ItemNumber>
<MoreData>some text here</MoreData>
<Address>address data</Address>
<Ranking>102</Ranking>
</ListItem>
<ListItem>
<Value>Another List Value</Value>
<Source>other.txt</Source>
<ListType>text</ListType>
<ItemNumber>7919</ItemNumber>
<MoreData>more text here</MoreData>
<Address>address data</Address>
<Ranking>41</Ranking>
</ListItem>
</ListTag>
</Field>
</MainTag>
我想要的是给我一个电子表格的查询结果,本质上是:
RecordID FieldName FieldValue ListValue ListSource ListType ListItemNumber …
201801026543210 TheFieldName Field Contents This List Value source.txt text 6912
201801026543210 TheFieldName Field Contents Another List Value other.txt text 7919
为了增加乐趣,XML 存储在 varchar 字段中,而不是 XML 字段。
作为我尝试过的示例数据和查询:
DECLARE @Tbl TABLE (
TblID varchar(15)
, Fld varchar(max)
)
INSERT INTO @Tbl SELECT '201801026543210', '<?xml version="1.0"?><MainTag xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RecordID="201801026543210"><Field Name="TheFieldName"><FieldValue>Field Contents</FieldValue><ListTag><ListItem><Value>This List Value</Value><Source>source.txt</Source><ListType>text</ListType><ItemNumber>6912</ItemNumber><MoreData>some text here</MoreData><Address>address data</Address><Ranking>102</Ranking></ListItem><ListItem><Value>Another List Value</Value><Source>other.txt</Source><ListType>text</ListType><ItemNumber>7919</ItemNumber><MoreData>more text here</MoreData><Address>address data</Address><Ranking>41</Ranking></ListItem></ListTag></Field></MainTag>'
-- this shows that i am reading the main tag
SELECT t.r.value('@RecordID','varchar(15)') AS RecordID
, t.r.query('.') as fullvalue
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
-- and this works to read the attribute from the first field
SELECT t.r.value('@RecordID', 'varchar(18)') AS RecordID
, f.r.value('@Name', 'varchar(100)') AS Field
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
CROSS APPLY Fld.nodes('/MainTag/Field') AS f(r)
-- this does NOT work to read the second field
SELECT t.r.value('@RecordID','varchar(18)') AS RecordID
, f.r.value('.', 'varchar(100)') AS ValueF
, p.r.query('.') AS QueryP
, p.r.value('.', 'varchar(100)') AS ValueP
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag') AS t(r)
CROSS APPLY Fld.nodes('/MainTag/Field') AS f(r)
CROSS APPLY Fld.nodes('/MainTag/FieldValue') AS p(r)
-- i honestly feel like this should be using nodes off of the parent nodes method
-- , but this is NOT working either
SELECT t.r.value('@RecordID','varchar(18)') AS RecordID
, p.r.query('.') AS FieldValue
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY s.Fld.nodes('/MainTag') AS t(r)
CROSS APPLY t.r.nodes('/MainTag/FieldValue') AS p(r)
我看到其他一些 questions/samples 只抓取第一个条目。我不要那个。我想要一大块数据。我希望每个 "ListItem" 重复唯一字段。换句话说:我知道这类似于一对多联接,其中 "one" table 中的字段将针对 "many" [=35= 中的每一行重复].
从技术上讲,在我的数据中可能还有不止一个 "Field"。
该字段只有一个 FieldValue。
存在一个或多个 ListItem。
用这个查询试试:
SELECT s.Fld.value('(/MainTag/@RecordID)[1]','bigint') AS RecordID
,A.f.value('@Name','nvarchar(max)') as FieldName
,A.f.value('(FieldValue/text())[1]','nvarchar(max)') as FieldValue
,B.li.value('(Value/text())[1]','nvarchar(max)') as ListValue
,B.li.value('(Source/text())[1]','nvarchar(max)') as ListSource
--and so on
FROM (
SELECT top 10 CONVERT(xml, Fld) AS Fld, TblID
FROM @Tbl
) AS s
CROSS APPLY Fld.nodes('/MainTag/Field') AS A(f)
CROSS APPLY A.f.nodes('ListTag/ListItem') AS B(li)
提示
如果有任何机会将存储从 VARCHAR
更改为 XML
,那是值得的...