Как сделать выборку выборку сотрудников по нескольким датам в 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 шт):

Автор решения: SVBazuev

Я бы очень хотел взглянуть на оригинальный текст задания!


С практической точки зрения решаться должно так:

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.


Замечания к Вашему решению:

  1. "Подзапрос" в блоке FROM основного запроса — это уже ПРЕДЗАПРОС. В этом случае лучше использовать ТАБЛИЧНОЕ ВЫРАЖЕНИЕ (Common Table Expression, CTE) - читаемость лучше.
  2. Странно, что перечисленные через запятую выборки (необходимо выбрать людей с датой приема на работу: от 0 и до 30 дней, от 7 дней и до 30 дней, от 14 и до 30 дней.), Вы выводите в одном запросе !? ...

Успехов!


UPD
Концепт верный, надо править детали в связи с уточнениями в вопросе. Сделаю это позже.

→ Ссылка
Автор решения: Akina

выбрать людей с датой приема на работу: от 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 дней

fiddle

PS. Знать бы, в чём отличие "от 0 и до 30 дней" и "до 30 дней"... или у вас осуществляется приём на работу "передним числом"?

→ Ссылка