Напишите запрос для вывода всех сотрудников

Хотите быстро вывести всех сотрудников из базы? Разбираем простой SQL-запрос SELECT с примерами, пояснениями и полезными хитростями для работы с таблицами.

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

+7 (800) 301-07-30

Реклама jurik.ru

Одной из самых базовых и часто используемых операций в работе с реляционными базами данных является выборка списка сотрудников. Независимо от того, используете ли вы Microsoft SQL Server, MySQL, PostgreSQL или Oracle, синтаксис базового запроса остается практически идентичным благодаря стандарту SQL-92. В этой статье мы разберем основные подходы, нюансы соединения таблиц (JOIN) и примеры из реальной практики, основанные на актуальных обсуждениях разработчиков (данные на ).

Базовый синтаксис: SELECT * FROM table

Самый простой способ вывести всех сотрудников — обратиться к таблице, хранящей кадровые данные. Часто она называется Staff, Employees, Users или Personal.

SELECT * FROM Staff;

Однако, как отмечается в профессиональной литературе (например, в курсах Coursehunters и книгах Алан Бьюли «Изучаем SQL»), использование звездочки (*) в продакшн-коде считается плохой практикой. Явное перечисление колонок делает запрос предсказуемее, быстрее (меньше трафика сети) и устойчивее к изменениям схемы БД.

Рекомендуемый вариант:

SELECT 
 T_number, -- Табельный номер (PK)
 Lastname, -- Фамилия
 Name, -- Имя
 Surname, -- Отчество
 Dept_id, -- ID отдела
 Position_id -- ID должности
FROM Staff;

Примечание: В примерах из сборников упражнений (Страница 2, Единое окно) часто используется таблица Staff с первичным ключом T_number и полями Name, Lastname, Surname.

Если в таблице могут дублироваться записи (например, история изменений зарплат в таблице Paies), для получения чистого списка людей используется ключевое слово DISTINCT.

Пример из учебных материалов (Упражнение 30):

SELECT DISTINCT 
 Name, 
 Lastname, 
 Surname 
FROM Staff;

Это гарантирует, что каждый сотрудник встретится в результате ровно один раз, даже если у него несколько записей в связанных таблицах (зарплаты, надбавки, истории переводов).

Связь с другими таблицами (JOIN): Отделы, Должности, Руководители

Реальные задачи почти всегда требуют не просто «ФИО», а контекст: название отдела, имя начальника, зарплатную статью. Здесь на помощь приходят JOIN.

Внутреннее соединение (INNER JOIN), только те, у кого есть связь

SELECT 
 s.Lastname, 
 s.Name, 
 s.Surname,
 d.DeptName AS Department
FROM Staff s
INNER JOIN Departments d ON s.Dept_id = d.Dept_id;

Левое соединение (LEFT JOIN) — все сотрудники, даже без отдела

Критически важно для HR-отчетов: если у сотрудника еще не проставлен отдел (Dept_id IS NULL), INNER JOIN его «съест». LEFT JOIN оставит строку, подставив NULL для полей отдела.

SELECT 
 s.Lastname, 
 s.Name, 
 d.DeptName
FROM Staff s
LEFT JOIN Departments d ON s.Dept_id = d.Dept_id;

Самосоединение (Self-JOIN) — вывод руководителя

Частая задача с Stack Overflow (mysql, sql-server): вывести сотрудника и его начальника в одной строке. Таблица ссылается на саму себя через Chief_ID (или Manager_ID).

SELECT 
 e1.Lastname AS Employee_Lastname,
 e1.Name AS Employee_Name,
 e2.Lastname AS Manager_Lastname,
 e2.Name AS Manager_Name
FROM Employee e1
LEFT JOIN Employee e2 ON e1.Chief_ID = e2.ID;

Совет с Хабр QA (2022): «Никак не сделать в одну строку данные один-ко-многим без агрегации». Если у одного начальника 10 подчиненных, будет 10 строк. Для «одной строки на начальника» нужны STRING_AGG (PostgreSQL/SQL Server 2017+), GROUP_CONCAT (MySQL) или LISTAGG (Oracle).

Рекурсивные запросы (CTE) — иерархия подчинения

Задача: «Вывести всех сотрудников в виде: Менеджер — сотрудники, менеджер — сотрудники (одним списком)». Обсуждалась на Хабр QA и Киберфорум. Решается через Рекурсивное CTE (Common Table Expression).

Пример для SQL Server / PostgreSQL / Oracle (стандарт ANSI SQL):

WITH RECURSIVE Hierarchy AS (
 -- Якорь: топ-менеджеры (у которых нет chefe)
 SELECT 
 ID, 
 Lastname, 
 Name, 
 Chief_ID, 
 0 AS Level,
 CAST(Lastname + ' ' + Name AS VARCHAR(MAX)) AS Path
 FROM Employee
 WHERE Chief_ID IS NULL

 UNION ALL

 -- Рекурсивная часть: подчиненные
 SELECT 
 e.ID, 
 e.Lastname, 
 e.Name, 
 e.Chief_ID, 
 h.Level + 1,
 CAST(h.Path + ' -> ' + e.Lastname + ' ' + e.Name AS VARCHAR(MAX))
 FROM Employee e
 INNER JOIN Hierarchy h ON e.Chief_ID = h.ID
)
SELECT * FROM Hierarchy ORDER BY Path;

Важно (Microsoft Learn, ): «Так как существует два уровня в иерархии, следует написать два запроса SELECT и применить предложение UNION ALL». Это упрощенный подход для фиксированной глубины, но рекурсивное CTE универсальнее.

Фильтрация и бизнес-логика (WHERE)

Часто нужно вывести не «всех», а выборку: «сотрудники с вычетом за бездетность», «сотрудники главного подразделения» и т.д.

Пример из сборника упражнений (Упражнение 29, 30):

-- Сотрудники, имевшие в зарплате статью "вычет за бездетность"
SELECT DISTINCT 
 s.Name, 
 s.Lastname, 
 s.Surname 
FROM Staff s
INNER JOIN Paies p ON s.T_number = p.T_number
INNER JOIN Items_pay ip ON p.Code_pay = ip.Code_pay
WHERE ip.Item_pay = 'за бездетность';

Проблема с подотделами (Stack Overflow, 2018):

Если нужно вывести сотрудников главного отдела, исключая подотделы:

SELECT s.* 
FROM Staff s
INNER JOIN Depts d ON s.Dept_id = d.Dept_id
WHERE d.Parent_Dept_ID IS NULL; -- Только главные отделы

Если убрать условие AND s.DeptName = 'Главное подразделение', запрос «раздувается» всеми подотделами. GROUP BY здесь не помогает, так как меняет гранулярность. Нужно правильно построить WHERE или использовать рекурсивное CTE для сбора дерева отделов.

Специфика СУБД: LIMIT / TOP / FETCH

Для вывода «первых N сотрудников» (например, для пагинации или теста) синтаксис разный:

  • MySQL / PostgreSQL / SQLite: SELECT * FROM Staff LIMIT 10;
  • SQL Server (до 2012): SELECT TOP 10 * FROM Staff;
  • SQL Server (2012+) / Oracle 12c+ / PostgreSQL (стандарт): SELECT * FROM Staff ORDER BY T_number OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

Продвинутые сценарии: Динамический SQL и временные таблицы

Согласно обсуждению на Хабр QA : «Только хранимая процедура, с временными таблицами и динамическим SQL. Про шанс выполнить эту задачу в виде одного запроса даже не заикайся». Это относится к задачам пивот-таблиц (Crosstab), когда колонки результата зависят от данных (например, «Вывести зарплаты за каждый месяц года колонками»). Для простого списка сотрудников это избыточно.

Чек-лист: Как написать идеальный запрос «Вывести всех сотрудников»

  1. Явно перечислите колонки (не используйте *).
  2. Используйте псевдонимы (алиасы) для таблиц (s, d, m), читаемость и скорость парсинга.
  3. Выбирайте правильный JOIN:
    • INNER JOIN — если связь обязательна (у всех есть отдел).
    • LEFT JOIN — если связь опциональна (есть сотрудники без отдела/начальника).
  4. Добавьте ORDER BY (по фамилии, табельному номеру или иерархии), иначе порядок строк не гарантирован.
  5. Используйте DISTINCT только если есть риск дублей из-за JOIN (один-ко-многим), и вам нужен плоский список уникальных людей.
  6. Маскируйте ПДн (Персональные Данные) в логах и тестовых выгрузках: * вместо телефонов, адресов, полных ФИО (если не нужно для отчета).
-- Универсальный запрос списка сотрудников с контекстом
SELECT 
 s;T_number AS TabNumber,
 s.Lastname AS LastName,
 s.Name AS FirstName,
 s.Surname AS MiddleName,
 d.DeptName AS Department,
 pos.PositionName AS Position,
 m.Lastname AS ManagerLastName,
 m.Name AS ManagerFirstName
FROM Staff s
LEFT JOIN Departments d ON s.Dept_id = d.Dept_id
LEFT JOIN Positions pos ON s.Position_id = pos.Position_id
LEFT JOIN Staff m ON s.Manager_ID = m.T_number -- Self-join для руководителя
WHERE s.Is_Active = 1 -- Только действующие (если есть флаг)
ORDER BY d.DeptName, s.Lastname, s.Name;

Резюме

Запрос SELECT * FROM Staff — это только вершина айсберга. Профессиональный подход подразумевает понимание структуры данных (PK/FK), выбор правильного типа соединения (JOIN), обработку иерархий (Recursive CTE) и учет специфики диалекта SQL вашей СУБД. Используйте приведенные шаблоны как отправную точку, адаптируя имена таблиц и колонок под вашу схему БД (например, для схемы HR_Schema на сервере ).

Статья подготовлена на основе актуальных данных сообществ Stack Overflow, Киберфорум, Хабр QA, Microsoft Learn и учебных материалов по SQL на .