При работе с данными о водительских правах часто требуется расширить набор выводимых столбцов: добавить вычисленные показатели, объединить информацию из связанных таблиц или сформировать произвольные метки для дальнейшего анализа. В этой статье мы рассмотрим несколько подходов, которые работают в самых популярных СУБД – SQL Server, PostgreSQL и MySQL. Каждый метод иллюстрируется практическими примерами, адаптированными под типовую схему хранения данных о водительских правах.
Основные понятия
- Пользовательская (вычисляемая) колонка – столбец, значение которого формируется в момент выполнения запроса с помощью выражений, функций или подзапросов.
- Алиас (псевдоним) – имя, присваиваемому вычисляемому столбцу, чтобы его можно было использовать в дальнейшем (например, в
ORDER BYили внешних запросах). - Конкатенация – объединение строковых значений, часто применяется для создания читаемых меток (ФИО, номер права и т.д.).
Добавление простой вычисляемой колонки
Самый прямой способ – указать выражение прямо в списке SELECT и задать ему алиас.
Пример для SQL Server
SELECT
DriverID,
LicenseNumber,
-- вычисляем возраст на момент выдачи права
DATEDIFF(year, BirthDate, IssueDate) AS AgeAtIssue,
-- формируем полное ФИО
CONCAT(LastName, ' ', FirstName, ISNULL(' ' + MiddleName, '')) AS FullName
FROM Drivers
WHERE LicenseType = 'B';
Пример для PostgreSQL
SELECT
driver_id,
license_number,
EXTRACT(year FROM age(birth_date, issue_date)) AS age_at_issue,
last_name || ' ' || first_name ||
CASE WHEN middle_name IS NOT NULL THEN ' ' || middle_name ELSE '' END AS full_name
FROM drivers
WHERE license_type = 'B';
Пример для MySQL
SELECT
DriverID,
LicenseNumber,
TIMESTAMPDIFF(YEAR, BirthDate, IssueDate) AS AgeAtIssue,
CONCAT(LastName, ' ', FirstName,
IF(MiddleName IS NOT NULL AND MiddleName <> '', CONCAT(' ', MiddleName), '')) AS FullName
FROM Drivers
WHERE LicenseType = 'B';
В каждом случае мы добавили две пользовательские колонки: AgeAtIssue (возраст на момент выдачи) и FullName (полное ФИО). Их можно сразу использовать в ORDER BY, GROUP BY или в дальнейших подзапросах.
Использование подзапросов в списке SELECT
Иногда нужное значение находится в другой таблице и требует агрегации или фильтрации. Подзапрос (скалярный) позволяет вернуть одно значение и поместить его в колонку результата.
Пример: количество штрафов у водителя (SQL Server)
SELECT
d.DriverID,
d.LicenseNumber,
(SELECT COUNT() FROM Fines f WHERE f.DriverID = d.DriverID) AS FineCount,
CASE
WHEN (SELECT COUNT() FROM Fines f WHERE f.DriverID = d.DriverID) > 3 THEN 'Много'
ELSE 'Мало'
END AS FineLevel
FROM Drivers d
WHERE d.LicenseType = 'B';
Здесь подзапрос считает количество штрафов для каждого водителя, а второй подзапрос используется в выражении CASE для формирования категориальной метки.
Пример: средний балл экзаменов (PostgreSQL)
SELECT
d.driver_id,
d.license_number,
(SELECT AVG(score) FROM exam_results er WHERE er.driver_id = d.driver_id) AS avg_exam_score
FROM drivers d
WHERE d.license_type = 'B';
Объединение таблиц через JOIN для добавления колонок
Если нужно добавить несколько столбцов из связанной таблицы, проще выполнить LEFT JOIN (или INNER JOIN) и выбрать нужные поля.
Пример: добавление данных о категории транспорта и сроке действия права (MySQL)
SELECT
d.DriverID,
d.LicenseNumber,
c.CategoryName,
c.ValidPeriodMonths,
DATE_ADD(d;IssueDate, INTERVAL c.ValidPeriodMonths MONTH) AS ExpirationDate
FROM Drivers d
LEFT JOIN LicenseCategories c ON d.CategoryID = c.CategoryID
WHERE d.LicenseType = 'B';
В результате мы получили колонки CategoryName, ValidPeriodMonths и вычисляемую дату окончания действия права.
Использование функций window (оконных функций)
Оконные функции позволяют добавить аналитические колонки, не collapsing строки (как делает GROUP BY). Это удобно для ранжирования, накопления итогов и т.п.
Пример: ранжирование водителей по количеству штрафов (PostgreSQL)
SELECT
d.driver_id,
d.license_number,
COUNT(f.fine_id) OVER (PARTITION BY d.driver_id) AS fine_total,
RANK OVER (ORDER BY COUNT(f.fine_id) DESC) AS fine_rank
FROM drivers d
LEFT JOIN fines f ON f.driver_id = d.driver_id
WHERE d.license_type = 'B'
GROUP BY d.driver_id, d.license_number;
Здесь COUNT(...) с OVER (PARTITION BY) считает штрафы для каждого водителя, а RANK строит общий рейтинг.
Динамическое формирование списка колонок (если набор неизвестен заранее)
В некоторых аналитических задачах набор пользовательских колонок зависит от входных параметров (например, пользователь выбирает, какие показатели вывести). Тогда применяется динамический SQL.
Краткий пример для SQL Server
DECLARE @cols NVARCHAR(MAX) = N'DriverID, LicenseNumber';
DECLARE @sql NVARCHAR(MAX);
-- suppose @selectedMetrics contains comma‑separated list like 'AgeAtIssue, FineCount'
SET @cols = @cols + N', ' + @selectedMetrics;
SET @sql = N'SELECT ' + @cols + N' FROM Drivers WHERE LicenseType = ''B'';';
EXEC sp_executesql @sql;
Аналогичные подходы работают в PostgreSQL (EXECUTE format(...)) и MySQL (PREPARE/EXECUTE).
Практические рекомендации при работе с данными о водительских правах
- Используйте понятные алиасы – они делают результат самодокументируемым и упрощают дальнейшую обработку в BI‑системах.
- Избегайте вычислений с высокой стоимостью в цикле – если функция вызывается для каждой строки (например, сложная пользовательская функция), рассмотрите предвычисление в материализованном представлении или временной таблице.
- Проверяйте типы данных – при конкатенации строк и чисел может возникнуть неявное приведение, приводящее к ошибкам или неожиданным результатам.
- Используйте индексы – для подзапросов и JOIN‑ов полезно иметь индексы по внешним ключам (
DriverID,CategoryIDи т.д.). - Тестируйте на репрезентативной выборке – перед запуском на продакшн‑данных проверьте запрос на небольшом подмножестве, чтобы убедиться в корректности вычислений.
Добавление пользовательских колонок в результат SELECT – фундаментальный прием для гибкого анализа данных о водительских правах. В зависимости от задачи можно выбрать:
- простое выражение с алиасом (возраст, ФИО, срок действия);
- скалярный подзапрос (агрегаты, проверки);
- JOIN для подключения справочных данных;
- оконные функции для ранжирования и накопленных показателей;
- динамический SQL, когда набор колонок определяется во время выполнения.
Сочетание этих техник позволяет построить мощные аналитические запросы, готовые к использованию в системах отчетности, дашбордах и машинном обучении. Надеюсь, приведённые примеры и рекомендации помогут вам эффективно расширять вывод SELECT‑запросов под ваши конкретные задачи анализа водительских прав.