2017-01-20 4 views
0

У меня есть простая таблица с только DATETIME.Как получить максимальную дату предыдущего года в наборе данных с помощью оконной функции в SQL Server

Мой вопрос в том, как я могу получить значение, относящееся к концу года предыдущего года, с помощью окна-функции?

Я пытался с этим запросом, но результатом является истекшим годом текущего года:

SELECT datefield, max(datefield) OVER (PARTITION BY YEAR(datefiled)) FROM foo 

Я использую 2012

Огромное спасибо всем SQL Server.

ответ

2

Если вы хотите отфильтровать записи, вам необходимо использовать пункт Where. Вам нужно что-то вроде этой не оконной функции.

SELECT TOP 1 WITH ties * 
FROM foo 
WHERE datefield <= Datefromparts(Year(Getdate()) - 1, 12, 31) 
ORDER BY datefield DESC 

или

SELECT * 
FROM foo 
WHERE datefield = (SELECT Max(datefield) AS last_date_prev_year 
        FROM foo 
        WHERE datefield <= Datefromparts(Year(Getdate()) - 1, 12, 31)) 
2

Я не думаю, что вам нужно использовать оконную функцию. Простой фильтр, объединенный с 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 
; 
+0

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

+0

Я добавил два новых примера. Я думаю, что вторая, вероятно, ближе всего к тому, что вы хотите. Это в основном ваш запрос в сочетании с функцией [dateadd] (https://msdn.microsoft.com/en-GB/library/ms186819.aspx?f=255&MSPPError=-2147217396). –