Sql пример for xml path: Примеры: Использование режима PATH — SQL Server
Содержание
T-SQL | Конкатенация строк
181
Работа с базами данных в .NET Framework — Оконные функции T-SQL — Конкатенация строк
Исходник базы данных
Как уже говорилось, в стандарте SQL определены только два типа функций упорядоченного набора: функции гипотетического набора (RANK, DENSE_RANK, PERCENT_RANK и CUME_DIST) и функции обратного распределения (PERCENTILE_DISC и PERCENTILE_CONT). Как я уже демонстрировал на примере функций сдвига, нет причины, по которой эта концепция не работала бы и для других функций. Основная идея состоит в том, что если это агрегирующая функция, результат вычислении которой зависит от порядка следования элементов, это возможный кандидат на функцию упорядоченного набора.
Возьмем такой классический пример как конкатенация строки. К сожалению, на настоящий момент не существует встроенной агрегирующей функции конкатенации строки, которая бы соединяла группу строк. Но допустим, что такая функция существует. Конечно же, у вас может возникнуть необходимость в конкатенации группы строк в некотором порядке, поэтому имеет смысл реализовать такую функцию как функцию упорядоченного набора с предложением WITHIN GROUP, которое позволяет задать параметры упорядочения.
В Oracle, например, такая функция реализована (называется LISTAGG) как функция упорядоченного набора. Итак, чтобы обратиться к таблице с именем Sales.Orders и вернуть для каждого клиента строку со значениями orderid конкатенированными в порядке orderid, используйте следующий код:
-- Для Oracle SELECT custid, LISTAGG(orderid, ',') WITHIN GROUP(ORDER BY orderid) AS custorders FROM Sales.Orders GROUP BY custid;
В SQL Server разработчики прибегают к самым разным альтернативным решениям, чтобы получить конкатенацию строк в определенном порядке. Один из наиболее эффективных приемов основывается на обработке XML с использованием параметра FOR XML в режиме PATH, примерно так:
SELECT custid, COALESCE( STUFF( (SELECT ',' + CAST(orderid AS VARCHAR(10)) AS [text()] FROM Sales.Orders AS O WHERE O.custid = C.custid ORDER BY orderid FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, ''), '') AS custorders FROM Sales.Customers AS C;
Расположенный на самом нижнем уровне вложения связанный вложенный запрос отфильтровывает только значения orderid из таблицы Orders (псевдоним O), которые связаны с текущим клиентом из таблицы Customers (псевдоним C). Используя предложение FOR XML PATH, можно объединить все значения одну строку XML. Использование пустой строки как входного значения в режиме PATH означает, что инкапсулирующие элементы не нужны, поэтому мы получаем конкатенацию значений без всяких тегов. Так как вложенный запрос содержит ORDER BY orderid, значения orderid в строке будут упорядочены. Заметьте, что упорядочивать можно по любому признаку — не обязательно по значениям, которые конкатенируются. Приведенный код также добавляет запятую в качестве разделителя перед каждым значением orderid, а затем функция STUFF удаляет первую запятую. И наконец, функция COALESCE преобразует результат NULL в пустую строку. Итак, мы видим, что существует возможность получить в SQL Server конкатенацию строк в определенном порядке, но выглядит это не очень изящно.
Итак, функции упорядоченного набора, которые мы рассмотрели ранее, это агрегирующие функции, результат вычисления которых зависит от упорядочения. В стандарте определено несколько специализированных функций, но принцип является общим и может применяться ко всем видам вычислений агрегатов. Я привел несколько примеров, выходящих за пределы поддерживаемого стандарта, — это функции смещения и конкатенация строк. SQL Server 2012 не поддерживает функции упорядоченного набора данных, но я привел альтернативные методы для получения аналогичной функциональности. Я очень надеюсь, что в будущем мы увидим в SQL Server поддержку таких функций — возможно, они будут реализовывать стандартное предложение WITHIN GROUP и будут доступны через пользовательские CLR-функции агрегирования, учитывающие упорядочение.
Группировка данных массива в одну строку.
Для MS SQL Server 2005 и выше.
Например, есть запрос по сотрудникам компании и отделам (на примере БД AdventureWorks):
USE AdventureWorks
SELECT
h.
d.Name AS [Department Name]
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.Department d ON d.DepartmentID = h.DepartmentID
WHERE h.EmployeeID in (96, 140, 274)
Нужно разработать запрос, в котором отделы по каждому сотруднику перечислялись бы в одной строке.
Например, для сотрудника [Employee ID] 274 запрос возвратил бы строку: ‘Marketing | Quality Assurance | Purchasing’.
Подобный запрос можно реализовать с помощью оператора STUFF:
—ШАБЛОН
—Крутим данные запроса: SELECT ID, [Name] FROM TableName
—[Name] — что крутим
—ID — по чему крутим
—‘ | ‘ — символ между значениями в скрученной строке
/*
select distinct t1.ID,
STUFF((SELECT distinct ‘ | ‘ + t2.
from (SELECT ID, [Name] FROM TableName
) t2
where t1.ID = t2.ID
FOR XML PATH(»), TYPE
).value(‘.’, ‘NVARCHAR(MAX)’)
,1,0,») data
from (SELECT ID, [Name] FROM TableName
) t1
*/
—ПРИМЕР (запрос по сотрудникам и отделам, в которых они работали; БД AdventureWorks MS SQL Server 2005)
—Крутим данные запроса:
— SELECT
— h.EmployeeID AS [Employee ID],
— d.Name AS [Department Name]
— FROM HumanResources.EmployeeDepartmentHistory h
— INNER JOIN HumanResources.Department d ON d.DepartmentID = h.DepartmentID
— WHERE h.EmployeeID in (96, 140, 274)
—[Department Name] в строку по [Employee ID]
USE AdventureWorks
select distinct t1.
STUFF((SELECT distinct ‘ | ‘ + t2.[Department Name]
from (SELECT
h.EmployeeID AS [Employee ID],
d.Name AS [Department Name]
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.Department d ON d.DepartmentID = h.DepartmentID
WHERE h.EmployeeID in (96, 140, 274)
) t2
where t1.[Employee ID] = t2.[Employee ID]
FOR XML PATH(»), TYPE
).value(‘.’, ‘NVARCHAR(MAX)’)
,1,0,») data
from (SELECT
h.EmployeeID AS [Employee ID],
d.Name AS [Department Name]
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.
WHERE h.EmployeeID in (96, 140, 274)
) t1
При желании, полученное поле можно отформатировать (привести к тексту, например VARCHAR(7000)*) и отбросить из строки первый избыточный символ (разделитель элементов массива, в примере это первые 3 символа):
USE AdventureWorks
select [Employee ID], CAST(RIGHT(data, LEN(data) — 3) AS VARCHAR(7000)) AS Department from (
select distinct t1.[Employee ID],
STUFF((SELECT distinct ‘ | ‘ + t2.[Department Name]
from (SELECT
h.EmployeeID AS [Employee ID],
d.Name AS [Department Name]
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.
WHERE h.EmployeeID in (96, 140, 274)
) t2
where t1.[Employee ID] = t2.[Employee ID]
FOR XML PATH(»), TYPE
).value(‘.’, ‘NVARCHAR(MAX)’)
,1,0,») data
from (SELECT
h.EmployeeID AS [Employee ID],
d.Name AS [Department Name]
FROM HumanResources.EmployeeDepartmentHistory h
INNER JOIN HumanResources.Department d ON d.DepartmentID = h.DepartmentID
WHERE h.EmployeeID in (96, 140, 274)
) t1
) Employee_Dept
*
Результат STUFF-а может быть в формате BLOB, который не всегда совместим с другими аналитическими и информационными системами
|
FOR XML в SQL Sever
Введение
В этой статье мы обсудим предложение FOR XML Path в SQL Server. Эта статья может быть полезна новичкам, специалистам среднего уровня или профессионалам.
Мы рассмотрим,
- Пример использования
- ДЛЯ XML
- АВТОМАТИЧЕСКИЙ режим с FOR XML
- Режим PATH с FOR XML
- Разница между режимом AUTO и режимом PATH.
- Директива Elements с FOR XML
- Режим RAW с FOR XML
- Режим EXPLICIT с FOR XML
Давайте начнем эту статью с варианта использования,
ПРИМЕР ИСПОЛЬЗОВАНИЯ
В современном мире XML играет жизненно важную роль в разработке, и мы часто получаем XML-данные в наших базах данных. Предложение FOR XML Path может помочь нам работать с XML-данными в SQL Server.
Предположим, у нас есть требование вернуть данные в формате XML из базы данных; мы должны использовать предложение FOR XML.
FOR XML в SQL Server
Предложение FOR XML можно использовать для преобразования существующих данных в формат XML. Он также может объединять или объединять несколько столбцов в одну строку.
Предложение FOR XML имеет ниже 4 режимов, которые определяют форму XML-результата.
- СЫРЬЕ
- АВТО
- ЯВНОЕ
- ПУТЬ
Синтаксис
[ FOR { BROWSE |} ] ::= XML { { RAW [('ИмяЭлемента') ] | АВТО } [ <Общие директивы> [ , {XMLDATA | XMLSCHEMA [('TargetNameSpaceURI') ]} ] [ , ЭЛЕМЕНТЫ [ XSINIL | ОТСУТСТВУЮЩИЙ ] ] | ЯВНЫЙ [ <Общие директивы> [ , XMLДАННЫЕ ] ] | ПУТЬ [('ИмяЭлемента')] [ <Общие директивы> [ , ЭЛЕМЕНТЫ [ XSINIL | ОТСУТСТВУЮЩИЙ ] ] ] } <Общие директивы> ::= [ , ДВОИЧНЫЙ BASE64 ] [ , ТИП ] [ , КОРЕНЬ [ ('Корневое имя') ] ]
АВТОМАТИЧЕСКИЙ РЕЖИМ С FOR XML
FOR XML AUTO и FOR XML PATH — это самые простые способы преобразования данных SQL в XML. В приведенном ниже примере мы обсудим предложение FOR XML AUTO.
Мы создадим таблицу членов и вставим несколько строк, чтобы показать демонстрацию в этой статье.
Член CREATE TABLE ( MemberId int identity(1,1) первичный ключ, Имя varchar(100), Фамилия varchar(100), Адрес varchar(100), Городской варчар(100), Состояние varchar(100), Номер телефона, целое число )
Теперь вставьте несколько строк,
INSERT INTO Member ЗНАЧЕНИЯ («Киртеш», «Шах», «Тестовый адрес», «Вадодара», «Гуджарат», «1234567890»), («Раджеш», «Шах», «Адрес Сурат», «Сурат», «Гуджарат», «2134567894»), («Радж», «Патель», «TestAddress2», «Вадодара», «Гуджарат», «176347896»), («Мегха», «Шах», «SuratAddress3», «Куча», «Гуджарат», «457896321»), («Виушал», «Патель», «TestAddress4», «Бхудж», «Гуджарат», «325468796»), («Махеш», «Шах», «SuratAddress5», «Сура», «Гуджарат», «186347896»)
Сначала мы выполним приведенный ниже запрос SELECT и увидим результат,
SELECT * FROM Member
OUTPUT
Теперь мы обсудим пример FOR XML AUTO,
SELECT * FROM Member FOR XML AUTO
9005 1 ВЫВОД
Щелкнем по XML, показанному выше. ,
ВЫВОД XML
Режим PATH с FOR XML
Давайте воспользуемся тем же запросом с FOR XML PATH.
SELECT * FROM Member FOR XML PATH
ВЫВОД
XML ВЫВОД
<строка>22 Киртеш Шах TestAddressВадодара <Штат>ГуджаратШтат> <номер телефона>1234567890номер телефона> строка> <строка>23 Раджеш Шах SuratAddressСурат <Штат>ГуджаратШтат>2134567894 строка> <строка>24 Радж Патель TestAddress2Вадодара <Штат>ГуджаратШтат> <номер телефона>176347896номер телефона> строка> <строка>25 Мега Шах SuratAddress3Куча <Штат>ГуджаратШтат>457896321 строка> <строка>26 Виушал Патель TestAddress4 <Город>БхуджГород> <Штат>ГуджаратШтат> <Номер телефона>325468796номер телефона> строка> <строка>27 Махеш Шах SuratAddress5Сура <Штат>ГуджаратШтат>186347896 строка>
Разница между FOR XML и XML Path
Давайте сравним вывод FOR XML AUTO и FOR XML PATH,
Как показано на изображении выше,
- FOR XML AUTO — Структурированный XML, где каждый столбец является атрибутом.
- FOR XML PATH — Структурированный XML, где каждая запись является элементом, а столбец становится вложенным элементом.
Директива элементов с FOR XML
В приведенном выше запросе добавлено имя элемента, как показано ниже
SELECT * FROM Member FOR XML PATH («Член»)
ВЫВОД
ВЫВОД XML
<Член>22 Киртеш Шах TestAddressВадодара <Штат>ГуджаратШтат>1234567890 Член> <Член>23 Раджеш Шах SuratAddressСурат <Штат>ГуджаратШтат> <Номер телефона>2134567894номер телефона> Член> <Член>24 Радж Патель TestAddress2Вадодара <Штат>ГуджаратШтат>176347896 Член> <Член>25 Мега Шах SuratAddress3Куча <Штат>ГуджаратШтат> <номер телефона>457896321номер телефона> Член> <Член>26 Виушал Патель TestAddress4 <Город>БхуджГород> <Штат>ГуджаратШтат>325468796 Член> <Член>27 Махеш Шах SuratAddress5Сура <Штат>ГуджаратШтат> <номер телефона>186347896номер телефона> Член>
Обратите внимание, что вместо
Режим RAW с FOR XML
Давайте посмотрим ниже запрос и вывод XML, чтобы лучше понять.
SELECT * FROM Member FOR XML RAW
ВЫВОД
XML ВЫВОД
ЯВНЫЙ РЕЖИМ с FOR XML
Предположим, вам нужны результаты XML в вашем формате; EXPLICIT – правильный выбор. Это даст вам гибкость для создания результата в вашем формате.
Синтаксис
<ЭЛЕМЕНТ>!<ТЕГ>!<АТРИБУТ>[!<ДИРЕКТИВА>]
Мы можем использовать приведенный выше синтаксис для генерации XML в желаемом формате.
Это все для этой статьи. Я надеюсь, что вы научитесь и найдете это полезным.
Создание списка, разделенного запятыми, с помощью FOR XML PATH и STUFF в SQL Server
Я не могу придумать историю или совет, который связан с созданием списка, разделенного запятыми, поэтому я просто использую тот, который совершенно не связан. Делиться опытом с близкими — это весело, и рыбалка — не исключение. Многие из моих недавних любимых рыболовных воспоминаний связаны с рыбалкой с моим четырехлетним сыном. Два лета назад, когда ему было два года, мы ловили морского окуня у пристани в хижине моего дедушки на севере Висконсина. Я цеплял их и позволял моему сыну ловить их маленькой сачком для бабочек, прежде чем отцепить их и отпустить. Я только что поймал на крючок еще одну и пытался подтянуть ее достаточно близко, чтобы мой сын мог поймать сеть, когда вдруг ворвалась крупная северная щука и полностью проглотила пойманного на крючок синежаберника. Увидев такую большую рыбу, мой сын быстро отступил. Северная щука вообще не попалась на крючок, но все же дралась со мной где-то полминуты, прежде чем выплюнуть синежабру. Это было то, чего большинство людей не увидит, и было весело испытать это на себе с моим сыном, который только начал заниматься рыбалкой.
Если вам нужно создать список, разделенный запятыми, в SQL Server, лучший способ сделать это — использовать предложение FOR XML PATH. Это берет набор данных и помещает его в формат, который можно использовать в XML. Синтаксис может быть немного сложным, поэтому давайте рассмотрим его поближе. Сначала я создам временную таблицу и заполню ее некоторыми значениями — мы будем использовать мускусные приманки:
CREATE TABLE #LureNames ( ID INT IDENTITY(1, 1) , Приманка VARCHAR(25) ) ВСТАВЬТЕ В #LureNames ( Приманка ) ЦЕННОСТИ ( "Убийца Меппса Маски"), («Гарассер»), ("Бухертейл 700"), ("Рифовый бегун"), («Крик Голавль Пайк Минноу»), («Бабушка»), («Джейк»), («Мелкий рейдер») ("Бульдог"), («Сумасшедший триллер»), («Верующий»), («Плавательный свист»), («Двойная ковбойша»), («Медусса»), ("Двойник"), ("Мелкий захватчик"), («Лучший рейдер») («Глубинный рейдер») («Кардиостимулятор»), («Богатый воблер»), («Мягкий фантом»)
Если мы выполним простой выбор из этой таблицы, мы получим ожидаемое:
Если мы хотим получить список, разделенный запятыми, мы используем этот синтаксис:
SELECT STUFF(( SELECT ', ' + Приманка ОТ ( ВЫБЕРИТЕ ОТЛИЧНЫЕ Приманка ОТ #LureNames ) Икс ДЛЯ ПУТЬ XML('') ), 1, 2, '') AllLures
Чтобы понять, что это делает, давайте начнем изнутри и пройдем наружу. В самой внутренней части довольно простой SELECT DISTINCT:
SELECT DISTINCT Приманка ОТ #LureNames
Это просто даст нам имя каждой приманки один раз:
На следующем шаге мы добавим запятые и вставим предложение FOR XML PATH.
ВЫБОР ', ' + Приманка ОТ ( ВЫБЕРИТЕ ОТЛИЧНЫЕ Приманка ОТ #LureNames ) Икс ДЛЯ XML-ПУТЬ
Вы можете видеть, что результаты теперь представлены в формате xml. Поскольку мы не указали имя столбца, записи называются просто
ВЫБОР ', ' + Приманка ОТ ( ВЫБЕРИТЕ ОТЛИЧНЫЕ Приманка ОТ #LureNames ) Икс FOR XML PATH('')
Теперь единственное, что нужно исправить, это ведущую запятую и пробел.