Иногда, в сложных запросах, требуется вывести данные из разных таблиц, при этом желательно за один шаг и без ущерба для производительности. Например, есть три таблицы: записи, метки (тэги), связь записей и меток. Требуется вывести список записей с метками.
Инструкции
Предполагается, что в базе есть таблицы:
entries - записи
tags - метки
entries_in_tags - связь записей с метками
Иногда, в сложных запросах, требуется вывести данные из разных таблиц, при этом желательно за один шаг и без ущерба для производительности.
Например, есть три таблицы: записи, метки (тэги), связь записей и меток. Требуется вывести список записей с метками.
Конечно, можно сделать один запрос на получение списка записей и далее делать дополнительные запросы к SQL Server непосредственно при выводи записи, но это негативно отразится на производительности.
Как вариант, можно написать отдельную SQL-функцию, которая будет возвращать список меток в определенном формате, например, через запятую, и использовать эту функцию в SQL-запросе получения списка записей. Если с метками такой способ вполне себя оправдает, то с чем-то более крупным, например, если потребуется вывести многострочные текстовые данные, возникнут проблемы, придется, откровенно говоря, извращаться. К тому же использование функций также негативно отразится на производительности.
В MS SQL Server для подобных задач существуют средства для работы с XML. См. примеры ниже.
-- вывод всех меток в формате XML при помощи инструкции FOR XML,
-- инструкции AUTO указывает на то,
-- что SQL Server сам определяет структуру XML-данных
SELECT * FROM tags FOR XML AUTO
-- вывод записей, и меток в колонку tags
SELECT e.*,
(SELECT tags.tag FROM entries_in_tags
INNER JOIN tags ON tags.id_tags = entries_in_tags.id_tags
WHERE id_entries = e.id_entries FOR XML AUTO) AS tags
FROM entries AS e
-- сами определяем структуру XML-данных
SELECT e.*,
(SELECT tags.tag AS '@tag' FROM entries_in_tags
INNER JOIN tags ON tags.id_tags = entries_in_tags.id_tags WHERE id_entries = e.id_entries
FOR XML PATH ('item'), TYPE, ELEMENTS, ROOT('root')) AS tags
FROM entries AS e