T- SQL Регулярное выражение в XML узлах метода () - PullRequest
0 голосов
/ 31 января 2020

У меня есть таблица T с двумя столбцами. Столбец A является столбцом varchar, а столбец B является столбцом XML.

Где-то внутри столбца B всегда есть следующий родительский тег: <Documents> ... </Documents>. Внутри есть несколько <Document>...</Document> потомков.

Я хотел бы получить набор результатов с двумя столбцами:

Столбец 1 должен содержать те же значения, что и столбец A; Столбец 2 должен содержать содержимое только одного <Document>...</Document>. Кроме того, в столбце 2 должны быть только <Document> s с атрибутом, равным 1, 2 или 3.

Например, Стартовая таблица T:

Column A | Column B
--------------------------------------------------------------------------
abc      | <Documents><Document ID="1">Doc Foo</Document><Document ID="4">Doc Bar</Document></Documents>
def      | <Documents><Document ID="2">Doc Foo2</Document><Document ID="3">Doc Bar2</Document></Documents>

Ожидаемый результат:

Column 1 | Column 2
-------------------------------------
abc      |<Document ID="1">Doc Foo</Document>
def      |<Document ID="2">Doc Foo2</Document>
def      |<Document ID="3">Doc Bar2</Document>

Я могу получить ожидаемый результат следующим образом:

SELECT
     [Column A]     AS [Column 1]
    ,T2.c.query('.') AS [Column 2]
FROM T AS tbl
    CROSS APPLY T.nodes('*/Documents/Document[@ID="1" or @ID="2" or @ID="3"]') AS T2(c)

Но когда условия фильтра становятся более сложными, он может выйти из-под контроля без регулярных выражений. Это не работает:

SELECT
     [Column A]      AS [Column 1]
    ,T2.c.query('.') AS [Column 2]
FROM T AS tbl
    CROSS APPLY T.nodes('*/Documents/Document[@ID="[1-3]"]') AS T2(c)

Как заставить это работать?

Ответы [ 3 ]

0 голосов
/ 31 января 2020

Вы можете отфильтровать атрибут, чтобы он отображался в последовательности значений:

Document[@ID = (1,2,3)]
0 голосов
/ 31 января 2020

Вы были очень близки. XQuery основан на понятии последовательностей. Поэтому вам необходимо проверить, является ли значение атрибута @ID членом последовательности.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID CHAR(3), xmldata XML);;
INSERT INTO @tbl (ID, xmldata)
VALUES
('abc', '<Documents><Document ID="1">Doc Foo</Document><Document ID="4">Doc Bar</Document></Documents>')
, ('def', '<Documents><Document ID="2">Doc Foo2</Document><Document ID="3">Doc Bar2</Document></Documents>');
-- DDL and sample data population, end

SELECT ID
    , c.query('.') AS [Column 2]
FROM @tbl AS tbl
    CROSS APPLY tbl.xmldata.nodes('/Documents/Document[@ID=("1","2","3")]') AS t(c);

Выход

+-----+--------------------------------------+
| ID  |               Column 2               |
+-----+--------------------------------------+
| abc | <Document ID="1">Doc Foo</Document>  |
| def | <Document ID="2">Doc Foo2</Document> |
| def | <Document ID="3">Doc Bar2</Document> |
+-----+--------------------------------------+
0 голосов
/ 31 января 2020

Чтобы расширить то, что предлагает @JeroenMostert, и если он прав, то, возможно, вы ищете:

WITH YourTable AS(
    SELECT *
    FROM (VALUES('abc',CONVERT(xml,'<Documents><Document ID="1">Doc Foo</Document><Document ID="4">Doc Bar</Document></Documents>')),
                ('def',CONVERT(xml,'<Documents><Document ID="2">Doc Foo2</Document><Document ID="3">Doc Bar2</Document></Documents>')))V(Col1,Col2))
SELECT YT.Col1,
       Ds.D.query('.')
FROM YourTable YT
     CROSS APPLY YT.Col2.nodes('Documents/Document') Ds(D)
WHERE Ds.D.value('@ID','int') IN (1,2,3);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...