Создание пользовательских колонок в T‑SQL

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

В работе с 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