简体   繁体   English

交叉应用返回太多行

[英]Cross apply returns too many rows

DDL: 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>')

Query: 查询:

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               

Output: 输出:

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

Required output: 要求的输出:

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

I am getting cross joins between the rows of <rp> data. 我在<rp>数据行之间出现交叉联接。

Also note if ag="0" I want to skip that data, it does, just it still joins that row. 还要注意,如果ag =“ 0”我想跳过该数据,它确实会跳过,只是它仍然联接该行。 I'm not sure how to join the <rp> to <re> or if it's at all possible. 我不确定如何将<rp>加入<re>或完全有可能。

You're using too many times CROSS APPLY. 您使用CROSS APPLY的次数过多。

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
\nStationID_q | StationID_q | ProgramID_s | ProgramID_s | StartTime_o StartTime_o        \n:----------------------------------- | :----------------------------------- | :----------------------------------- | :----------------------------------- | :------------------ :------------------\n000000cb-0000-0000-0000-000000000000 | 000000cb-0000-0000-0000-000000000000 | 00a566e2-0000-0000-0000-000000000000 | 00a566e2-0000-0000-0000-000000000000 | 10/01/2018 17:00:00 10/01/2018 17:00:00\n000000cb-0000-0000-0000-000000000000 | 000000cb-0000-0000-0000-000000000000 | 00a5860a-0000-0000-0000-000000000000 | 00a5860a-0000-0000-0000-000000000000 | 26/01/2018 17:00:00 26/01/2018 17:00:00\n000000cb-0000-0000-0000-000000000000 | 000000cb-0000-0000-0000-000000000000 | 00a595c0-0000-0000-0000-000000000000 | 00a595c0-0000-0000-0000-000000000000 | 29/01/2018 17:00:00 29/01/2018 17:00:00\n

dbfiddle here dbfiddle 在这里

This approach reads the meta data out of the XML directly and needs only one single CROSS APPLY and no WHERE (the filter is included into nodes() in the predicate ): 这种方法直接从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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM