交叉应用返回太多行

时间:2018-03-20 19:48:24

标签: sql sql-server xml tsql cross-apply

DDL:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="dropdown">
    <span>Label</span>
    <ul>
      <li>Option 1</li>
      <li>Option 2</li>
      <li>Option 3</li>
      <li>Option 4</li>
    </ul>
  </div>
</div>

<div class="body-content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel tellus sit amet diam sagittis tempor. Nullam sed nunc non ipsum rhoncus tincidunt. Ut odio nisi, convallis et augue vitae, dictum semper mauris. Donec ullamcorper vehicula mi in interdum. Cras at hendrerit dolor, a scelerisque arcu. Nullam sagittis consectetur hendrerit. Donec interdum gravida tincidunt. Morbi id sem eleifend, gravida urna sit amet, vestibulum nibh. Pellentesque non convallis massa. Vivamus non metus lobortis, condimentum lorem vitae, semper augue. Ut eget ante eget orci elementum sodales. Donec nec ligula mauris.</p>

<p>Nunc a consectetur nulla, vel viverra velit. Maecenas sagittis velit turpis, eu dapibus turpis blandit vitae. Duis mollis, lorem ac consectetur hendrerit, turpis odio lacinia eros, sed lacinia velit justo in est. Integer non mauris lacinia, sagittis justo sed, accumsan tortor. Suspendisse a commodo tortor. Etiam tincidunt mi sit amet elementum fringilla. Pellentesque luctus ac leo non lobortis. Morbi iaculis consequat lacus eget tristique. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus ultrices congue augue, vel consequat velit viverra sed. Sed a finibus velit. Mauris sed orci lectus. Vivamus bibendum ante et quam volutpat, sed venenatis mi dignissim. Ut tempus iaculis faucibus.</p>
</div>

查询:

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 数据行之间进行交叉连接。

另请注意,如果ag =“0”我想跳过那些数据,它会这样做,只是它仍然加入那一行。我不确定如何加入<rp><rp>,或者如果可能的话。

2 个答案:

答案 0 :(得分:0)

你使用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
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

答案 1 :(得分:0)

此方法直接从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);