Функция EOMONTH

Как узнать последний день месяца по заданной дате, например, текущего месяца?

Текущую дату мы можем узнать, используя встроенную функцию current_timestamp:

select current_timestamp;
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Чтобы узнать последний день предыдущего месяца, мы можем от текущей даты отнять номер текущего дня месяца, т.е. количество дней, прошедших от начала месяца:

select dateadd(dd, -day(current_timestamp), current_timestamp);
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Тогда для текущего месяца нам потребуется предварительно добавить один месяц к текущей дате:

select dateadd(dd, -day(dateadd(mm, 1, current_timestamp)),
               dateadd(mm, 1, current_timestamp));
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Уберем, наконец, из полученного результата компоненту времени:

select cast(
dateadd(dd, -day(dateadd(mm, 1, current_timestamp)), dateadd(mm, 1, current_timestamp))
as date);
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

В SQL Server 2012 появилась функция EOMONTH, которая позволяет сделать то же самое без применения “процедурной” логики:

select cast(
            dateadd(dd, -day(dateadd(mm, 1, current_timestamp)),
            dateadd(mm, 1, current_timestamp)) as date
            ) old_way, 
       eomonth(current_timestamp) new_way;
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Если вы получаете ошибку при выполнении последнего запроса, значит учебник еще не переехал на версию SQL Server, поддерживающую EOMONTH.

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

old_waynew_way
2016-07-312016-07-31

Мы уже знаем, что функция EOMONTH имеет аргументом выражение типа даты. Кроме того, функция имеет также второй (необязательный) целочисленный аргумент, представляющий число месяцев, которые, при наличии, будут добавлены к дате, представленной первым аргументом. Например, следующий запрос даст нам последние дни предыдущего, текущего и следующего месяца для даты ‘2016-01-28’:

select eomonth('2016-01-28',-1) prev_month,
       eomonth('2016-01-28') this_month,
       eomonth('2016-01-28', 1) next_month;
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]
prev_monththis_monthnext_month
2015-12-312016-01-312016-02-29