SQL: Как выбрать несколько xml узлов с одинаковым именем в списке через запятую - PullRequest
0 голосов
/ 05 марта 2020

Предположим, у вас есть поле XML в таблице базы данных, которое выглядит следующим образом:

<PEOPLE>
  <PERSON>
    <FIRST_NAME>John</FIRST_NAME>
    <LAST_NAME>Doe</LAST_NAME>
  </PERSON>
  <PERSON>
    <FIRST_NAME>Jane</FIRST_NAME>
    <LAST_NAME>Doe</LAST_NAME>
  </PERSON>
</PEOPLE>

И вы хотели внести имена всех людей в список через запятую (например, «Джон Доу, Джейн Доу»). Прямо сейчас мой SQL запрос выглядит так:

SELECT STUFF((
  SELECT ', ' + FIRST_NAME + ' ' + LAST_NAME
  FROM(
    SELECT
      p.value('(./FIRST_NAME)[1]', 'nvarchar(max)') as FIRST_NAME,
      p.value('(./LAST_NAME)[1]', nvarchar(max)') as LAST_NAME
    FROM [TABLE]
    CROSS APPLY [FIELD].nodes('PEOPLE/PERSON') t(p)
  ) PEOPLE_ROWS
FOR XML PATH('')), 1, 1, '') COMMA_SEPARATED_LIST

Сейчас это работает просто отлично, и я получаю хороший список через запятую, но я подумал, что есть более простой способ сделать это. Есть ли маги xpath c, которые дают результаты симлара?

1 Ответ

0 голосов
/ 06 марта 2020

Это относительно легко реализовать с помощью выражений XQuery и FLWOR.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata)
VALUES
(N'<PEOPLE>
  <PERSON>
    <FIRST_NAME>John</FIRST_NAME>
    <LAST_NAME>Doe</LAST_NAME>
  </PERSON>
  <PERSON>
    <FIRST_NAME>Jane</FIRST_NAME>
    <LAST_NAME>Smith</LAST_NAME>
  </PERSON>
</PEOPLE>');
-- DDL and sample data population, end

DECLARE @separator CHAR(1) = ',';

SELECT ID
    , xmldata.query('for $i in /PEOPLE/PERSON
        let $person := concat(data($i/FIRST_NAME[1])," ",data($i/LAST_NAME[1]))
        return if ($i is (/PEOPLE/PERSON[last()])[1]) then $person
                else concat($person, sql:variable("@separator"))')
         .value('.', 'NVARCHAR(MAX)') AS [Comma_separated_list]
FROM @tbl;

Вывод

+----+--------------------------+
| ID | Comma_separated_list     |
+----+--------------------------+
|  1 | John Doe, Jane Smith     |
+----+--------------------------+
...