交叉应用 returns 行过多
Cross apply returns too many rows
DDL:
CREATE TABLE [testXML]
(
[scheduleid] [uniqueidentifier] primary key,
[XMLData1] [xml] NULL
)
INSERT INTO testXML ([scheduleid],XMLData1)
VALUES ('88888888-DDDD-4444-AAAA-666666666666','<ArrayOfRDData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RDData h="Title" o="2017-11-02T16:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" an="203" >
<rps>
<rp s="00a566e2-0000-0000-0000-000000000000" ag="1" i="0" j="0" ah="2018-01-10T17:00:00Z" >
<piData programId="00a566e2-0000-0000-0000-000000000000" al="0" />
<res>
<re o="2018-01-10T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" >
<riData av="false" az="201" />
</re>
</res>
</rp>
<rp s="00a5860a-0000-0000-0000-000000000000" ag="1" i="0" j="0" ah="2018-01-26T17:00:00Z" >
<piData programId="00a5860a-0000-0000-0000-000000000000" al="1" />
<res>
<re o="2018-01-26T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" >
<riData av="false" az="201" />
</re>
</res>
</rp>
<rp s="00a595c4-0000-0000-0000-000000000000" ag="0" i="0" j="0" ah="2018-01-31T17:00:00Z" >
<piData programId="00a595c4-0000-0000-0000-000000000000" al="2" />
<res>
<re o="2018-01-31T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" />
</res>
</rp>
<rp s="00a595c0-0000-0000-0000-000000000000" ag="1" i="0" j="0" ah="2018-01-29T17:00:00Z" >
<piData programId="00a595c0-0000-0000-0000-000000000000" al="3" />
<res>
<re o="2018-01-29T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" >
<riData av="false" az="180" />
</re>
</res>
</rp>
</rps>
</RDData>
</ArrayOfRDData>')
查询:
SELECT
[scheduleid],
StationID_q = ARD3.res.value('@q', 'varchar(max)'),
ProgramID_s = ARD2.ag.value('@s', 'varchar(max)'),
StartTime_o = ARD3.res.value('@o', 'datetime')
FROM
[DVR_0601].[dbo].testXML Sch
CROSS APPLY
Sch.XMLData1.nodes('/ArrayOfRDData/RDData/rps') AS AoD(RDData)
CROSS APPLY
AoD.RDData.nodes('rp') AS ARD2(ag)
CROSS APPLY
AoD.RDData.nodes('rp/res/re') AS ARD3(res)
WHERE
ISNULL( ARD2.ag.value('@ag', 'int'), 0) = 1
输出:
StationID_q ProgramID_s StartTime_o
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-31 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-31 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-31 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
要求输出:
StationID_q ProgramID_s StartTime_o
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
我在 <rp>
数据行之间进行交叉连接。
另请注意,如果 ag="0" 我想跳过该数据,确实如此,只是它仍然加入该行。我不确定如何加入 <rp>
到 <re>
或者是否可能。
您使用交叉应用的次数过多。
SELECT --[scheduleid],
StationID_q = ARD3.res.value('@q', 'varchar(max)'),
ProgramID_s = ARD2.ag.value('@s', 'varchar(max)'),
StartTime_o = ARD3.res.value('@o', 'datetime')
FROM testXML Sch
---------------- all rp nodes
CROSS APPLY Sch.XMLData1.nodes('/ArrayOfRDData/RDData/rps/rp') AS ARD2(ag)
---------------- all inner res/re nodes from rp tag
CROSS APPLY ag.nodes('res/re') AS ARD3(res)
WHERE ISNULL(ARD2.ag.value('@ag', 'int'), 0) = 1
StationID_q | ProgramID_s | StartTime_o
:----------------------------------- | :----------------------------------- | :------------------
000000cb-0000-0000-0000-000000000000 | 00a566e2-0000-0000-0000-000000000000 | 10/01/2018 17:00:00
000000cb-0000-0000-0000-000000000000 | 00a5860a-0000-0000-0000-000000000000 | 26/01/2018 17:00:00
000000cb-0000-0000-0000-000000000000 | 00a595c0-0000-0000-0000-000000000000 | 29/01/2018 17:00:00
dbfiddle here
这种方法直接从 XML 中读取元数据,只需要一个 CROSS APPLY
而不需要 WHERE
(过滤器包含在 nodes()
中谓词):
SELECT testXML.XMLData1.value('(/ArrayOfRDData/RDData/@q)[1]','uniqueidentifier') AS StationID
,a.rps.value('@s','uniqueidentifier') AS ProgramID
,a.rps.value('(res/re/@o)[1]','datetime') AS StartTime
FROM testXML
CROSS APPLY testXML.XMLData1.nodes('/ArrayOfRDData/RDData/rps/rp[@ag!=0]') AS a(rps);
DDL:
CREATE TABLE [testXML]
(
[scheduleid] [uniqueidentifier] primary key,
[XMLData1] [xml] NULL
)
INSERT INTO testXML ([scheduleid],XMLData1)
VALUES ('88888888-DDDD-4444-AAAA-666666666666','<ArrayOfRDData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RDData h="Title" o="2017-11-02T16:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" an="203" >
<rps>
<rp s="00a566e2-0000-0000-0000-000000000000" ag="1" i="0" j="0" ah="2018-01-10T17:00:00Z" >
<piData programId="00a566e2-0000-0000-0000-000000000000" al="0" />
<res>
<re o="2018-01-10T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" >
<riData av="false" az="201" />
</re>
</res>
</rp>
<rp s="00a5860a-0000-0000-0000-000000000000" ag="1" i="0" j="0" ah="2018-01-26T17:00:00Z" >
<piData programId="00a5860a-0000-0000-0000-000000000000" al="1" />
<res>
<re o="2018-01-26T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" >
<riData av="false" az="201" />
</re>
</res>
</rp>
<rp s="00a595c4-0000-0000-0000-000000000000" ag="0" i="0" j="0" ah="2018-01-31T17:00:00Z" >
<piData programId="00a595c4-0000-0000-0000-000000000000" al="2" />
<res>
<re o="2018-01-31T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" />
</res>
</rp>
<rp s="00a595c0-0000-0000-0000-000000000000" ag="1" i="0" j="0" ah="2018-01-29T17:00:00Z" >
<piData programId="00a595c0-0000-0000-0000-000000000000" al="3" />
<res>
<re o="2018-01-29T17:00:00Z" p="212" q="000000cb-0000-0000-0000-000000000000" >
<riData av="false" az="180" />
</re>
</res>
</rp>
</rps>
</RDData>
</ArrayOfRDData>')
查询:
SELECT
[scheduleid],
StationID_q = ARD3.res.value('@q', 'varchar(max)'),
ProgramID_s = ARD2.ag.value('@s', 'varchar(max)'),
StartTime_o = ARD3.res.value('@o', 'datetime')
FROM
[DVR_0601].[dbo].testXML Sch
CROSS APPLY
Sch.XMLData1.nodes('/ArrayOfRDData/RDData/rps') AS AoD(RDData)
CROSS APPLY
AoD.RDData.nodes('rp') AS ARD2(ag)
CROSS APPLY
AoD.RDData.nodes('rp/res/re') AS ARD3(res)
WHERE
ISNULL( ARD2.ag.value('@ag', 'int'), 0) = 1
输出:
StationID_q ProgramID_s StartTime_o
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-31 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-31 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-31 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
要求输出:
StationID_q ProgramID_s StartTime_o
000000cb-0000-0000-0000-000000000000 00a566e2-0000-0000-0000-000000000000 2018-01-10 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a5860a-0000-0000-0000-000000000000 2018-01-26 17:00:00.000
000000cb-0000-0000-0000-000000000000 00a595c0-0000-0000-0000-000000000000 2018-01-29 17:00:00.000
我在 <rp>
数据行之间进行交叉连接。
另请注意,如果 ag="0" 我想跳过该数据,确实如此,只是它仍然加入该行。我不确定如何加入 <rp>
到 <re>
或者是否可能。
您使用交叉应用的次数过多。
SELECT --[scheduleid],
StationID_q = ARD3.res.value('@q', 'varchar(max)'),
ProgramID_s = ARD2.ag.value('@s', 'varchar(max)'),
StartTime_o = ARD3.res.value('@o', 'datetime')
FROM testXML Sch
---------------- all rp nodes
CROSS APPLY Sch.XMLData1.nodes('/ArrayOfRDData/RDData/rps/rp') AS ARD2(ag)
---------------- all inner res/re nodes from rp tag
CROSS APPLY ag.nodes('res/re') AS ARD3(res)
WHERE ISNULL(ARD2.ag.value('@ag', 'int'), 0) = 1
StationID_q | ProgramID_s | StartTime_o :----------------------------------- | :----------------------------------- | :------------------ 000000cb-0000-0000-0000-000000000000 | 00a566e2-0000-0000-0000-000000000000 | 10/01/2018 17:00:00 000000cb-0000-0000-0000-000000000000 | 00a5860a-0000-0000-0000-000000000000 | 26/01/2018 17:00:00 000000cb-0000-0000-0000-000000000000 | 00a595c0-0000-0000-0000-000000000000 | 29/01/2018 17:00:00
dbfiddle here
这种方法直接从 XML 中读取元数据,只需要一个 CROSS APPLY
而不需要 WHERE
(过滤器包含在 nodes()
中谓词):
SELECT testXML.XMLData1.value('(/ArrayOfRDData/RDData/@q)[1]','uniqueidentifier') AS StationID
,a.rps.value('@s','uniqueidentifier') AS ProgramID
,a.rps.value('(res/re/@o)[1]','datetime') AS StartTime
FROM testXML
CROSS APPLY testXML.XMLData1.nodes('/ArrayOfRDData/RDData/rps/rp[@ag!=0]') AS a(rps);