В работе с Microsoft SQL Server часто возникает необходимость вывести не просто «сырой» набор столбцов из таблицы‚ а сформировать пользовательские колонки – вычисляемые поля‚ объединения‚ переименования‚ а иногда и динамически генерируемый набор столбцов. В этой статье мы подробно разберём‚ какие возможности предоставляет язык T‑SQL для создания таких колонок‚ как их правильно использовать в SELECT‚ а также рассмотрим типичные сценарии: алиасы‚ вычисляемые столбцы‚ конкатенация‚ условные выражения‚ агрегаты‚ PIVOT и динамический SQL.
Основы: алиасы и простая переименовка колонок
Самый простой способ «настроить» колонку – задать ей псевдоним (alias). Это делается с помощью ключевого слова AS (можно опустить‚ но рекомендуется для читаемости).
SELECT
CustomerID AS ID_Клиента‚
FirstName AS Имя‚
LastName AS Фамилия‚
BirthDate AS Дата_Рождения
FROM dbo.Customers;
В результате в результирующем наборе столбцы будут отображаться под новыми названиями‚ что упрощает восприятие отчётов.
Алиасы без AS
SELECT
ProductName Имя_Товара‚
Price Стоимость
FROM dbo.Products;
Только помните‚ что если имя алиаса содержит пробелы или специальные символы‚ его необходимо заключать в квадратные скобки [ ] или двойные кавычки.
Псевдонимы в ORDER BY и GROUP BY
Алиасы‚ объявленные в SELECT‚ могут использоваться в ORDER BY и GROUP BY (но не в WHERE).
SELECT
YEAR(OrderDate) AS Год‚
COUNT(*) AS Кол_во_заказов
FROM dbo.Orders
GROUP BY YEAR(OrderDate)
ORDER BY Год DESC;
Вычисляемые (выражения) колонки
Часто требуется вывести значение‚ полученное в результате вычисления над другими колонками. В T‑SQL это делается прямо в списке SELECT.
Арифметические вычисления
SELECT
ProductID‚
Quantity‚
UnitPrice‚
Quantity * UnitPrice AS Сумма_Без_НДС‚
Quantity * UnitPrice * 1.2 AS Сумма_С_НДС -- 20% НДС
FROM dbo.OrderDetails;
Конкатенация строк
Для объединения текста используют оператор + (или функцию CONCAT).
SELECT
EmployeeID‚
FirstName‚
LastName‚
FirstName + ' ' + LastName AS ФИО‚
CONCAT(FirstName‚ ' '‚ LastName) AS ФИО_2
FROM dbo.Employees;
Условные выражения (CASE)
SELECT
OrderID‚
TotalAmount‚
CASE
WHEN TotalAmount > 10000 THEN 'Большой заказ'
WHEN TotalAmount > 5000 THEN 'Средний заказ'
ELSE 'Малый заказ'
END AS Категория_заказа
FROM dbo.Orders;
Функции даты и времени
SELECT
OrderID‚
OrderDate‚
DATEDIFF(day‚ OrderDate‚ GETDATE) AS Дней_с_заказа‚
FORMAT(OrderDate‚ 'dd.MM.yyyy') AS Дата_в_формате
FROM dbo.Orders;
Работа с несколькими значениями в одной колонке
В вопросе пользователя упоминалось‚ что «не получается вывести более 1 разного текста» в одной колонке. Для этого используют конкатенацию или агрегатные функции‚ такие как STRING_AGG (SQL Server 2017+).
Конкатенация фиксированного набора значений
SELECT
'Один‚ Два‚ Три‚ Четыре' AS Список_Текстов;
Объединение строк из нескольких записей
SELECT
CustomerID‚
STRING_AGG(ProductName‚ '‚ ') AS Список_Товаров
FROM dbo.OrderDetails od
JOIN dbo.Products p ON od.ProductID = p.ProductID
GROUP BY CustomerID;
Если версия сервера старше 2017‚ можно использовать FOR XML PATH(''):
SELECT
CustomerID‚
STUFF((
SELECT '‚ ' + ProductName
FROM dbo.OrderDetails od2
JOIN dbo.Products p2 ON od2.ProductID = p2.ProductID
WHERE od2.CustomerID = od.CustomerID
FOR XML PATH('')‚ TYPE).value('.'‚'nvarchar(max)')‚1‚2‚'') AS Список_Товаров
FROM dbo.OrderDetails od
GROUP BY CustomerID;
Поворот (PIVOT) и разворот (UNPIVOT) данных
Иногда требуется преобразовать строки в столбцы (и наоборот). Для этого в SQL Server есть операторы PIVOT и UNPIVOT.
Пример PIVOT – продажи по месяцам
SELECT *
FROM (
SELECT
YEAR(OrderDate) AS Год‚
DATENAME(month‚ OrderDate) AS Месяц‚
TotalAmount
FROM dbo.Orders
) AS src
PIVOT (
SUM(TotalAmount)
FOR Месяц IN ([January]‚[February]‚[March]‚[April]‚[May]‚[June]‚
[July]‚[August]‚[September]‚[October]‚[November]‚[December])
) AS pvt
WHERE Год = 2023;
Пример UNPIVOT – «распаковать» несколько колонок в строки
SELECT EmployeeID‚ Параметр‚ Значение
FROM (
SELECT EmployeeID‚ Salary‚ Bonus‚ Tax
FROM dbo.EmployeeCompensation
) AS src
UNPIVOT (
Значение FOR Параметр IN (Salary‚ Bonus‚ Tax)
) AS unpvt;
Динамический набор колонок
Если список колонок заранее неизвестен (например‚ список продуктов меняется)‚ используют динамический SQL. Ниже – пошаговый шаблон.
DECLARE @cols NVARCHAR(MAX);
DECLARE @query NVARCHAR(MAX);
-- 1. Формируем список колонок через STRING_AGG
SELECT @cols = STRING_AGG(QUOTENAME(ProductName)‚ '‚')
FROM (SELECT DISTINCT ProductName FROM dbo.Sales) AS d;
-- 2. Формируем запрос с PIVOT
SET @query = N'
SELECT *
FROM (
SELECT
SalesDate‚
ProductName‚
Amount
FROM dbo.Sales
) AS src
PIVOT (
SUM(Amount) FOR ProductName IN (' + @cols + N')
) AS pvt;';
-- 3. Выполняем
EXEC sp_executesql @query;
Важно: при работе с динамическим SQL всегда проверяйте входные данные‚ чтобы избежать SQL‑инъекций.
Практические рекомендации
- Явно указывайте алиасы. Это делает код самодокументируемым.
- Используйте функции
CONVERT/CASTилиFORMATдля приведения типов. Особенно полезно при выводе дат и чисел в пользовательском виде. - Не перегружайте один запрос множеством вычислений. Если логика сложная‚ вынесите её в
VIEWили вSCALAR FUNCTION. - Для больших наборов данных используйте агрегаты и индексы. Вычисляемые колонки в
SELECTне влияют на план выполнения‚ но могут увеличить нагрузку на процессор. - Тестируйте запросы в SSMS. В Microsoft SQL Server Management Studio (SSMS) удобно просматривать результаты‚ копировать их в Excel и проверять корректность алиасов.
Пример полного запроса с несколькими типами пользовательских колонок
/*
Отчёт «Продажи сотрудников за текущий год»:
— ФИО сотрудника (конкатенация)
— Сумма продаж (агрегат)
─ Средний чек (AVG)
─ Категория объёма продаж (CASE)
─ Дата последней продажи (MAX‚ формат)
*/
SELECT
e.EmployeeID‚
CONCAT(e.FirstName‚ ' '‚ e.LastName) AS ФИО‚
SUM(o.TotalAmount) AS Сумма_Продаж‚
AVG(o.TotalAmount) AS Средний_Чек‚
CASE
WHEN SUM(o.TotalAmount) > 500000 THEN 'VIP'
WHEN SUM(o.TotalAmount) > 200000 THEN 'Премиум'
ELSE 'Стандарт'
END AS Категория_Клиента‚
FORMAT(MAX(o.OrderDate)‚ 'dd.MM.yyyy') AS Последняя_Продажа
FROM dbo.Employees e
JOIN dbo.Orders o ON e.EmployeeID = o.SalesPersonID
WHERE YEAR(o.OrderDate) = YEAR(GETDATE)
GROUP BY e.EmployeeID‚ e.FirstName‚ e.LastName
ORDER BY Сумма_Продаж DESC;
В этом запросе использованы:
- конкатенация строк для ФИО;
- агрегатные функции
SUM‚AVG‚MAX; - условный оператор
CASEдля классификации; - форматирование даты через
FORMAT; - алиасы‚ которые делают вывод понятным.
Настройка пользовательских колонок в SELECT запросе – это мощный инструмент‚ позволяющий адаптировать вывод под нужды аналитики‚ отчётности и бизнес‑логики без изменения структуры таблиц. С помощью алиасов‚ вычисляемых выражений‚ условных операторов‚ агрегатов‚ PIVOT/UNPIVOT и динамического SQL вы получаете гибкость‚ необходимую для решения практически любой задачи.
Не забывайте проверять полученный набор данных в SQL Server Management Studio‚ использовать индексы для ускорения агрегаций и всегда писать читаемый код – это сэкономит время как вам‚ так и вашим коллегам.
Дата публикации: 17:02:49