В SQL Server 2005 и более поздних версиях вы можете использовать общее табличное выражение (CTE) в сочетании с функциями ROW_NUMBER()
и PARTITION BY
. Этот CTE «разделит» ваши данные по одному критерию - в вашем случае Client
, создав «раздел» для каждого отдельного клиента. ROW_NUMBER()
будет затем нумеровать каждый раздел, упорядоченный по другим критериям - здесь я создал DATETIME
- и назначать номера от 1 и выше, отдельно для каждого раздела.
Таким образом, в этом случае, упорядочивая по DATETIME DESC
, самая новая строка нумеруется как 1 - и это тот факт, который я использую при выборе из CTE. Я использовал здесь функцию ISNULL()
, чтобы присвоить тем строкам, которые имеют NULL end_date
какое-то произвольное значение, чтобы "привести их в порядок". Я не совсем уверен, правильно ли я понял ваш вопрос: вы хотите выбрать строки NULL вместо строк с данным end_Date
или вы хотите отдать приоритет существующему значению end_Date
над NULL?
Это выберет самую последнюю строку для каждого клиента (для каждого «раздела» ваших данных):
DECLARE @clients TABLE (Client CHAR(1), Program CHAR(1), END_DATE DATETIME)
INSERT INTO @clients
VALUES('a', 'b', '20090505'),
('a', 'd', '20100808'),
('a', 'f', '20110303'),
('h', 'd', '20090909'),
('h', 'f', NULL)
;WITH LatestData AS
(
SELECT Client, Program, End_Date,
ROW_NUMBER() OVER(PARTITION BY CLient ORDER BY ISNULL(End_Date, '99991231') DESC) AS 'RowNum'
FROM @clients
)
SELECT Client, Program, End_Date
FROM LatestData
WHERE RowNum = 1
Результат:
Client Program End_Date
a f 2011-03-03
h f (NULL)