Как объединить текст из нескольких строк в одну текстовую строку в SQL Server
Рассмотрим таблицу базы данных с именами, содержащую три строки:
Peter
Paul
Mary
Существует ли простой способ превратить это в одну строку вида Peter, Paul, Mary?
В SQL Server можно объединить несколько строк в одну текстовую строку с помощью нескольких методов, при этом наиболее современным подходом является функция STRING_AGG, доступная в SQL Server 2017 и более поздних версиях, или традиционный метод FOR XML PATH для более старых версий. Для вашего примера с именами вы бы использовали STRING_AGG(Name, ', ') для получения результата Peter, Paul, Mary.
Содержание
- Современный подход: функция STRING_AGG
- Традиционный метод: FOR XML PATH
- Продвинутые методы и соображения
- Сравнение производительности
- Практические примеры для разных сценариев
- Обработка значений NULL и специальных случаев
Современный подход: функция STRING_AGG
Функция STRING_AGG является наиболее простым и читаемым методом, доступным в SQL Server 2017 и более поздних версиях. Эта функция агрегирует значения из нескольких строк в одну строку с указанным разделителем.
Базовый синтаксис:
STRING_AGG ( выражение, разделитель ) [ ( order_by_clause ) ]
Для вашего примера с именами:
SELECT STRING_AGG(Name, ', ') AS ConcatenatedNames
FROM YourTable;
Ключевые особенности:
- Автоматически обрабатывает значения NULL (по умолчанию исключает их)
- Позволяет упорядочивать результаты с помощью предложения
ORDER BY - Более читаемый и поддерживаемый, чем FOR XML PATH
- Лучшая производительность для больших наборов данных
Пример с упорядочиванием:
SELECT STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name)
FROM YourTable;
Примечание: Функция
STRING_AGGявляется рекомендуемым подходом для современных сред SQL Server благодаря своей простоте и преимуществам производительности.
Традиционный метод: FOR XML PATH
До SQL Server 2017 разработчики commonly использовали метод FOR XML PATH для объединения нескольких строк. Этот подход использует функциональность XML для соединения строковых значений.
Базовый синтаксис:
SELECT STUFF(
(SELECT ', ' + Name
FROM YourTable
FOR XML PATH('')),
1, 2, ''
) AS ConcatenatedNames;
Как это работает:
- Подзапрос объединяет каждое имя с запятой и пробелом
FOR XML PATH('')преобразует результаты в формат XML- Функция
STUFFудаляет ведущую запятую и пробел
Альтернатива без STUFF:
SELECT REPLACE(
(SELECT Name + ', '
FROM YourTable
FOR XML PATH('')),
', ', ', ')
AS ConcatenatedNames;
Важно: Этот метод более сложен и требует тщательной обработки разделителей и возможных значений NULL.
Продвинутые методы и соображения
Разные варианты разделителей
Вы можете использовать различные разделители в зависимости от ваших требований:
-- Разделитель-пробел
SELECT STRING_AGG(Name, ' ') FROM YourTable;
-- Разделитель-точка с запятой
SELECT STRING_AGG(Name, '; ') FROM YourTable;
-- Разделитель-новая строка
SELECT STRING_AGG(Name, CHAR(13) + CHAR(10)) FROM YourTable;
Условная агрегация
SELECT STRING_AGG(
CASE WHEN Status = 'Active' THEN Name END,
', '
) FROM YourTable;
Групповое объединение
SELECT Department, STRING_AGG(EmployeeName, ', ')
FROM Employees
GROUP BY Department;
Уникальные значения
SELECT STRING_AGG(DISTINCT Name, ', ') FROM YourTable;
Сравнение производительности
| Метод | Производительность | Читаемость | Поддержка версий | Обработка NULL |
|---|---|---|---|---|
| STRING_AGG | Отличная | Высокая | SQL Server 2017+ | Автоматическое исключение |
| FOR XML PATH | Хорошая | Низкая | Все версии | Ручная обработка |
| COALESCE | Средняя | Средняя | Все версии | Ручная обработка |
Результаты тестирования производительности:
STRING_AGGобычно работает в 2-3 раза быстрее, чемFOR XML PATHна больших наборах данных- Использование памяти более эффективно с
STRING_AGG - План выполнения показывает более оптимизированные планы запросов с новой функцией
Практические примеры для разных сценариев
Пример 1: Простое объединение имен
-- Структура таблицы
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
FirstName VARCHAR(50),
LastName VARCHAR(50),
Department VARCHAR(50)
);
-- Данные: Peter, Paul, Mary в отделе Sales
INSERT INTO Employees VALUES
(1, 'Peter', 'Smith', 'Sales'),
(2, 'Paul', 'Johnson', 'Sales'),
(3, 'Mary', 'Williams', 'Sales');
-- Использование STRING_AGG
SELECT STRING_AGG(FirstName + ' ' + LastName, ', ')
FROM Employees
WHERE Department = 'Sales';
Результат: Peter Smith, Paul Johnson, Mary Williams
Пример 2: Обработка смешанных типов данных
SELECT STRING_AGG(
CAST(Value AS VARCHAR(100)),
', '
) AS ConcatenatedValues
FROM MixedValuesTable;
Пример 3: Создание списков с разделителями-запятыми для отчетов
SELECT
OrderID,
STRING_AGG(ProductName, ', ') WITHIN GROUP (ORDER BY ProductName) AS Products
FROM OrderDetails
GROUP BY OrderID;
Обработка значений NULL и специальных случаев
Обработка значений NULL
-- STRING_AGG по умолчанию исключает NULL
SELECT STRING_AGG(Name, ', ') FROM YourTable;
-- Включить значения NULL как строку 'NULL'
SELECT STRING_AGG(
CASE WHEN Name IS NULL THEN 'NULL' ELSE Name END,
', '
) FROM YourTable;
Обработка пустых строк
-- Заменить пустые строки-заглушки
SELECT STRING_AGG(
CASE WHEN Name = '' THEN '[Empty]' ELSE Name END,
', '
) FROM YourTable;
Обработка больших наборов результатов
-- Использовать тип данных MAX для очень длинных объединенных строк
SELECT STRING_AGG(
Description,
CHAR(13) + CHAR(10)
) WITHIN GROUP (ORDER BY Description) AS LongText
FROM LargeTable;
Вопросы безопасности
-- Предотвращение SQL-инъекций путем параметризации значений
DECLARE @Separator VARCHAR(10) = ', ';
SELECT STRING_AGG(Name, @Separator) FROM YourTable;
Для вашего конкретного примера с тремя именами (Peter, Paul, Mary) самое простое решение в SQL Server 2017+ будет:
SELECT STRING_AGG(Name, ', ') AS ConcatenatedNames
FROM YourTable;
Это вернет именно то, что вам нужно: Peter, Paul, Mary.
Источники
- Microsoft Docs - STRING_AGG (Transact-SQL)
- SQL Server Central - Concatenating Multiple Rows into One String
- Stack Overflow - Best way to concatenate multiple rows into one string in SQL Server
- MSSQLTips - STRING_AGG vs FOR XML PATH Performance
Заключение
- Выберите правильный метод: Используйте
STRING_AGGдля сред SQL Server 2017+, так как он более читабелен и лучше работает, в то время какFOR XML PATHостается жизнеспособным вариантом для более старых версий - Правильно обрабатывайте значения NULL: Учтите, хотите ли вы исключать или включать значения NULL в ваши объединенные результаты
- Учитывайте производительность: Для больших наборов данных
STRING_AGGобычно обеспечивает лучшую производительность, чем традиционные методы - Тестируйте с вашими данными: Всегда тестируйте методы объединения с вашим конкретным объемом и структурой данных
- Планируйте будущее обслуживание: Хотя
FOR XML PATHработает,STRING_AGGявляется современным стандартом и легче для понимания другими разработчиками
Наиболее простое решение для вашего примера - использование STRING_AGG(Name, ', '), которое легко преобразует ваши три строки с именами в желаемый формат Peter, Paul, Mary.