Я не думаю, что вам нужно использовать оконную функцию. Простой фильтр, объединенный с max function, вернется в конце прошлого года.
-- Where clause removes records from current and future years.
SELECT
MAX(datefield)
FROM
foo
WHERE
YEAR(datefield) < YEAR(GETDATE())
;
Несмотря на простой подход, этот подход имеет небольшую проблему. Используя year function, на datefield
в предложении where, делает запрос non-sargable. Если производительность является проблемой; вы можете исправить, используя DateFromParts, как показано в точном ответе @ Prdp.
EDIT
Эта версия запроса использует оконную функцию, в соответствии с просьбой ОП.
-- Max of previous year, using a windowed function.
SELECT
MAX(datefield) AS LastYearEnd
FROM
(
-- Rank records based on year.
-- Current year is 1, last year is 2, etc.
SELECT
datefield,
DENSE_RANK() OVER (ORDER BY YEAR(datefield) DESC) AS rn
FROM
foo
) AS dr
WHERE
rn = 2
;
Вышеуказанный только возврат одной записи. Если вы хотите увидеть в последний день прошлого года, рядом с каждой записью в вашей таблице:
-- Returns last day of previous year, relative to dateField.
SELECT
datefield,
DATEADD(YEAR, -1, MAX(datefield) OVER (PARTITION BY YEAR(datefield)))
FROM
foo
;
Спасибо за ваш ответ, но моя цель состоит в том, чтобы достичь результата с оконной функцией. У меня нет проблем с производительностью, просто вопрос дизайна запроса – stexcec
Я добавил два новых примера. Я думаю, что вторая, вероятно, ближе всего к тому, что вы хотите. Это в основном ваш запрос в сочетании с функцией [dateadd] (https://msdn.microsoft.com/en-GB/library/ms186819.aspx?f=255&MSPPError=-2147217396). –