Выберите список дат из поля xml на сервере SQL - PullRequest
3 голосов
/ 14 января 2020

Я пытаюсь выбрать даты из следующих XML:

<output xmlns="http://www.abcde.com/pqwlv/dwh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="46177" xsi:schemaLocation="dwhOutput.xsd">
  <parameter>
    <isCoupon>0</isCoupon>
  </parameter>
  <schedule>
    <executionDate businessDay="2020-01-09">2020-01-09</executionDate>
    <endDates>
      <item businessDay="2019-03-18">2019-03-17</item>
      <item businessDay="2019-06-17">2019-06-17</item>
      <item businessDay="2019-09-17">2019-09-17</item>
      <item businessDay="2019-12-17">2019-12-17</item>
      <item businessDay="2020-03-17">2020-03-17</item>
      <item businessDay="2020-06-17">2020-06-17</item>
    </endDates>
  </schedule>
</output>

И я хочу выбрать список дат ("businessDay") из поля "endDates", поэтому вывод будет (в виде таблицы):

endDates
----------
2019-03-18
2019-06-17
2019-09-17
2019-12-17
2020-03-17
2020-06-17

Я пытался использовать этот запрос:

SELECT endDates.query('.') AS endDates
FROM [table]
CROSS APPLY
OUTPUT.nodes('declare namespace ns="http://www.abcde.com/pqwlv/dwh"; /ns:output/ns:schedule/ns:endDates') AS T1(endDates) 

И получил:

<p1:endDates xmlns:p1="http://www.abcde.com/pqwlv/dwh">
  <p1:item businessDay="2019-03-18">2019-03-17</p1:item>
  <p1:item businessDay="2019-06-17">2019-06-17</p1:item>
  <p1:item businessDay="2019-09-17">2019-09-17</p1:item>
  <p1:item businessDay="2019-12-17">2019-12-17</p1:item>
  <p1:item businessDay="2020-03-17">2020-03-17</p1:item>
  <p1:item businessDay="2020-06-17">2020-06-17</p1:item>
</p1:endDates>

Как я могу копать глубже и выберите даты?

Ответы [ 3 ]

1 голос
/ 14 января 2020

Вы были не далеко. Вам нужно использовать WITH XMLNAMESPACES в начале вашего запроса, чтобы определить пространство имен, а затем вы можете пересечь узлы в FROM:

DECLARE @xml xml = '<output xmlns="http://www.abcde.com/pqwlv/dwh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="46177" xsi:schemaLocation="dwhOutput.xsd">
  <parameter>
    <isCoupon>0</isCoupon>
  </parameter>
  <schedule>
    <executionDate businessDay="2020-01-09">2020-01-09</executionDate>
    <endDates>
      <item businessDay="2019-03-18">2019-03-17</item>
      <item businessDay="2019-06-17">2019-06-17</item>
      <item businessDay="2019-09-17">2019-09-17</item>
      <item businessDay="2019-12-17">2019-12-17</item>
      <item businessDay="2020-03-17">2020-03-17</item>
      <item businessDay="2020-06-17">2020-06-17</item>
    </endDates>
  </schedule>
</output>';

WITH XMLNAMESPACES(DEFAULT 'http://www.abcde.com/pqwlv/dwh',
                   'http://www.w3.org/2001/XMLSchema-instance' AS xsi)
SELECT eD.item.value('@businessDay','date') AS endDate
FROM (VALUES(@XML))V(YourXML) --This would be your table
     CROSS APPLY V.YourXML.nodes('/output/schedule/endDates/item') eD(item);
0 голосов
/ 14 января 2020

Кажется, здесь самый быстрый и чистый метод. Нет необходимости объявлять пространство имен xsi , поскольку оно не используется.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, xml_data XML);
INSERT INTO @tbl
VALUES (N'<output xmlns="http://www.abcde.com/pqwlv/dwh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        id="46177" xsi:schemaLocation="dwhOutput.xsd">
    <parameter>
        <isCoupon>0</isCoupon>
    </parameter>
    <schedule>
        <executionDate businessDay="2020-01-09">2020-01-09</executionDate>
        <endDates>
            <item businessDay="2019-03-18">2019-03-17</item>
            <item businessDay="2019-06-17">2019-06-17</item>
            <item businessDay="2019-09-17">2019-09-17</item>
            <item businessDay="2019-12-17">2019-12-17</item>
            <item businessDay="2020-03-17">2020-03-17</item>
            <item businessDay="2020-06-17">2020-06-17</item>
        </endDates>
    </schedule>
</output>');
-- DDL and sample data population, end

;WITH XMLNAMESPACES(DEFAULT 'http://www.abcde.com/pqwlv/dwh')
SELECT ID
    , col.value('.','DATE') AS endDates
FROM @tbl AS tbl
    CROSS APPLY tbl.xml_data.nodes('/output/schedule/endDates/item/@businessDay') AS tab(col);

Выход

+----+------------+
| ID |  endDates  |
+----+------------+
|  1 | 2019-03-18 |
|  1 | 2019-06-17 |
|  1 | 2019-09-17 |
|  1 | 2019-12-17 |
|  1 | 2020-03-17 |
|  1 | 2020-06-17 |
+----+------------+
0 голосов
/ 14 января 2020

Вы близки к желаемому выходу.

SELECT  T1.endDates.value('@businessDay','DATE')
FROM(
SELECT @X AS COL
)A 
CROSS APPLY
A.COL.nodes('declare namespace ns="http://www.abcde.com/pqwlv/dwh"; 
/ns:output/ns:schedule/ns:endDates/ns:item') AS T1(endDates) 

Выход:

(No column name)
2019-03-18
2019-06-17
2019-09-17
2019-12-17
2020-03-17
2020-06-17
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...