Как сделать выборку выборку сотрудников по нескольким датам в SQL?
Всем добрый день. Есть список сотрудников с датой према. По задаче необходимо выбрать людей с датой приема на работу: от 0 и до 30 дней, от 7 дней и до 30 дней, от 14 и до 30 дней.
Сотрудников которые работают до 30 дней, выбрал в дополнительном подзапросе.
WHERE CAST(hire_date AS DATE) >= DATEADD(day, -30, GETDATE())
Таблица с сотруднкиами.
SELECT @@VERSION;
create table personTest (
id bigint primary key ,
name varchar(10) not null,
hire_date DATE,
);
insert into personTest values (1, 'One', '2025-05-16 00:00:00.000');
insert into personTest values (2, 'Two', '2025-05-15 00:00:00.000');
insert into personTest values (3, 'Three', '2025-05-19 00:00:00.000')
insert into personTest values (4, 'Four', '2025-05-08 00:00:00.000')
insert into personTest values (5, 'Five', '2025-05-01 00:00:00.000')
insert into personTest values (6, 'Six', '2025-05-23 00:00:00.000')
insert into personTest values (7, 'Seven', '2025-05-20 00:00:00.000')
insert into personTest values (8, 'Eight', '2025-05-23 00:00:00.000')
insert into personTest values (9, 'Nine', '2025-05-29 00:00:00.000')
insert into personTest values (10, 'Ten', '2025-04-18 00:00:00.000')
insert into personTest values (11, 'Eleven', '2025-01-10 00:00:00.000')
Выборка
DECLARE
@date_first INT = 0
,@date_second INT = 7
,@date_third INT = 14
SELECT
*
,CONVERT(VARCHAR, cols.hire_date, 104) AS date_format
,CASE
-- Если со дня приема прошло 0, но меньше 30 дней выполяется условие 1.
WHEN count_day <= @date_first THEN 1
-- Если со дня приема прошло 7, но меньше 30 дней выполяется условие 2.
WHEN count_day <= @date_second THEN 2
-- Если со дня приема прошло 14 дней, но меньше 30 выполяется условие 3.
WHEN count_day <= @date_third THEN 3
ELSE 0
END AS value_date
FROM (
SELECT
*
,ABS(DATEDIFF(day, GETDATE(), hire_date)) AS count_day
FROM personTest
WHERE CAST(hire_date AS DATE) >= DATEADD(day, -30, GETDATE())
) AS cols
Пример в песочнице
На изображении, логика настраевыемые способом. AdjustDate - функция которая сдвигает дату. Смысл логики на изоражении такой - агент выбирает людей у кого от даты приема прошло 0 дней назначает одни курсы, у кого 7 дней назначает другие и треий вариант у кого прошло с тады приема 14 дней то уже 3 вид курсов.

Поменял местами числа проверки (14, 7, 0), работает как мне надо было .
SELECT
cols.id
,CASE
WHEN count_day >= 14 THEN 1
WHEN count_day >= 7 THEN 2
WHEN count_day >= 0 THEN 3
ELSE 0
END AS value_date
FROM (
SELECT
id
,position_id
,code
,hire_date
,ABS(DATEDIFF(day, GETDATE(), hire_date)) AS count_day
FROM [webtutor_test].[dbo].[collaborators]
WHERE is_dismiss != 1
AND current_state NOT IN ('Декрет')
UNION ALL
SELECT
id
,position_id
,code
,hire_date
,ABS(DATEDIFF(day, GETDATE(), hire_date)) AS count_day
FROM [webtutor_test].[dbo].[collaborators]
WHERE is_dismiss != 1
AND current_state IS NULL
) AS cols
INNER JOIN [webtutor_test].[dbo].[position] AS pos ON pos.id = cols.position_id
CROSS APPLY pos.data.nodes('/position/custom_elems/custom_elem[name="position_function"]') AS fields(pos_function)
CROSS APPLY (
SELECT pos_function.value('(/position/custom_elems/custom_elem[name="position_function"]/value)[1]', 'VARCHAR(4)') AS position_function_value
) AS pf
WHERE cols.code NOT LIKE '%puls%'
AND CAST(cols.hire_date AS DATE) >= DATEADD(day, -30, GETDATE())
AND pf.position_function_value IS NOT NULL
AND pf.position_function_value LIKE '%105%'
Ответы (2 шт):
Я бы очень хотел взглянуть на оригинальный текст задания!
С практической точки зрения решаться должно так:
DECLARE
@date_key INT = 14;
WITH ThirtyDaysCTE AS (
SELECT *,
ABS(DATEDIFF(day, GETDATE(), hire_date)) AS count_day,
CONVERT(VARCHAR, hire_date, 104) AS date_format
FROM persontest
WHERE hire_date >= DATEADD(DAY, -30, GETDATE())
)
SELECT *,
CAST(@date_key AS VARCHAR) + ' - 30' AS interval_days -- если это требуется
FROM ThirtyDaysCTE
WHERE count_day >= @date_key;
На проде @date_key заменится агрументом приходящим с веб-интерфейса $1.
Замечания к Вашему решению:
- "Подзапрос" в блоке
FROMосновного запроса — это уже ПРЕДЗАПРОС. В этом случае лучше использовать ТАБЛИЧНОЕ ВЫРАЖЕНИЕ (Common Table Expression, CTE) - читаемость лучше. - Странно, что перечисленные через запятую выборки (
необходимо выбрать людей с датой приема на работу: от 0 и до 30 дней, от 7 дней и до 30 дней, от 14 и до 30 дней.), Вы выводите в одном запросе !? ...
Успехов!
UPD
Концепт верный, надо править детали в связи с уточнениями в вопросе.
Сделаю это позже.
выбрать людей с датой приема на работу: от 0 и до 30 дней, от 7 дней и до 30 дней, от 14 и до 30 дней.
-- если нужно группы по всем условиям в одном запросе
WITH cte AS (
SELECT id, name, hire_date, DATEDIFF(day, hire_date, GETDATE()) AS amount
FROM personTest
)
SELECT id, name, hire_date,
CASE WHEN amount BETWEEN 0 AND 30 THEN 1 ELSE 0 END from0to30, -- от 0 и до 30 дней
CASE WHEN amount BETWEEN 7 AND 30 THEN 1 ELSE 0 END from7to30, -- от 7 и до 30 дней
CASE WHEN amount >= 14 THEN 1 ELSE 0 END from14, -- от 14 дней
CASE WHEN amount <= 30 THEN 1 ELSE 0 END to30 -- до 30 дней
FROM cte;
-- если нужен список по каждому условию отдельным запросом
SELECT id, name, hire_date
FROM personTest
WHERE DATEDIFF(day, hire_date, GETDATE()) BETWEEN 7 AND 30; -- от 7 и до 30 дней
PS. Знать бы, в чём отличие "от 0 и до 30 дней" и "до 30 дней"... или у вас осуществляется приём на работу "передним числом"?