SQL Server: сообщить о самой последней записи, если она не содержит NULL - PullRequest
0 голосов
/ 08 октября 2019

У меня есть следующая таблица, сотрудники:

employee_name contract_end_date
Nancy         03/01/2019
Nancy         02/01/2019
Nancy         01/01/2019
John          03/01/2019
John          02/01/2019
John          01/01/2019
John          NULL

В приведенном выше сценарии я хочу сообщить о самой последней записи Нэнси, потому что она не имеет активной записи (в NULL не указан NULL в contract_end_date), вот что у меня есть:

SELECT employee_name , MAX(contract_end_date) as contract_end_date 
FROM [dbo].[employees_test]
WHERE contract_end_date IS NOT NULL
GROUP BY employee_name

Я также получаю Джона в выводе из запроса выше:

employee_name   contract_end_date
John            2019-03-01
Nancy           2019-03-01

Что я должен изменить в коде, чтобы получить:

Nancy           2019-03-01

Ответы [ 4 ]

2 голосов
/ 08 октября 2019

Вы можете использовать row_number и подзапрос, чтобы отфильтровать нулевые записи, как показано ниже:

;with cte as (
    select *, row_number() over(partition by employee_name order by contract_end_date desc) as rown from #employee 
    where employee_name not in (
        select employee_name from #employee where contract_end_date is null
    )
)
select employee_name, contract_end_date from cte where rown = 1

Запрос прикреплен здесь https://rextester.com/DMG55580

1 голос
/ 08 октября 2019

Ваш запрос возвращает уникальные имена и максимальные конечные даты из любой записи, которая не равна нулю в contract_end_date.

Самое быстрое решение, которое у меня есть, это просто исключить любые имена в вашей таблице, которые имеют значение null в contract_end_date, используя подзапрос.

SELECT  employee_name, MAX(contract_end_date) as "contract_end_date"
FROM    [dbo].[employees_test]
WHERE   employee_name not in (SELECT employee_name
                              FROM   [dbo].[employees_test]
                              WHERE  contract_end_date is null
                              GROUP  BY employee_name);

Возможно, существует более оптимизированный подход, который может илиможет не понадобиться в зависимости от размера стола.

1 голос
/ 08 октября 2019

NULL исключается в функциях агрегирования. Вы можете назначить специальное значение для NULL:

SELECT employee_name , MAX(ISNULL(contract_end_date,N'9999-12-31')) as contract_end_date 
FROM [dbo].[employees_test]
GROUP BY employee_name
HAVING MAX(ISNULL(contract_end_date,N'9999-12-31'))<>N'9999-12-31'
0 голосов
/ 08 октября 2019

Вы просто хотите TOP (1), вам не нужно агрегировать:

SELECT TOP (1)
       employee_name,
       contract_end_date
FROM dbo.employees_test
WHERE contract_end_date IS NOT NULL
ORDER BY contract_end_date DESC;

Редактировать: Время хрустального шара:

SELECT TOP (1) WITH TIES
       employee_name,
       contract_end_date
FROM dbo.employees_test
WHERE contract_end_date IS NOT NULL
ORDER BY ROW_NUMBER() OVER (ORDER BY contract_end_date desc);
...