Заданное время даты фильтрует результаты по месяцам этого времени даты

#sql-server-2008

#sql-server-2008

Вопрос:

Для sql server 2008: каков наилучший способ фильтрации результатов, чтобы возвращать только результаты, относящиеся к тому же месяцу, что и определенная дата?

Лучшее, что я мог придумать, это следующее:

 -- set up test data
DECLARE @TABLE1 AS TABLE (
    ID INT,
    STRING VARCHAR(MAX),
    DATECOLUMN DATETIME
)
INSERT INTO @TABLE1
SELECT
    0 ID,
    'TABLE1 0' STRING,
    CONVERT(DATETIME, '2016-10-13 12:45:00', 102) DATECOLUMN
UNION ALL SELECT 1, 'TABLE1 1', CONVERT(DATETIME, '2016-9-13 12:45:00', 102)
UNION ALL SELECT 2, 'TABLE1 2', CONVERT(DATETIME, '2016-10-1 00:00:00', 102)
UNION ALL SELECT 3, 'TABLE1 3', CONVERT(DATETIME, '2016-10-31 23:59:59', 102)

-- set up constraint
DECLARE @SOMEDATE DATETIME = CONVERT(DATETIME, '2016-10-13 12:45:00', 102)

-- filter
SELECT * FROM @TABLE1
WHERE MONTH(DATECOLUMN) = MONTH(@SOMEDATE)
 

Это лучший способ?

Комментарии:

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

Ответ №1:

Ваш запрос вернет записи, в которых месяц DateColumn совпадает с месяцем @SomeDate , хотя (как указывает @Jayvee) это будет верно независимо от года. Так что, если это то, что вы хотите, ваше решение подойдет.

Но вы спросили, было ли это лучшим решением. Я бы сказал, нет, потому что это не будет использовать преимущества любого индекса, который у вас может быть, который включает DateColumn .

Итак, это то, что я бы сделал, если бы я был на SQL Server 2008:

  declare @someDate datetime  = GetDate()
 declare @startDate date
 declare @endDate date

 -- I want the first day of the month, at 12:00:00AM (no time component).
 -- The DateAdd expression subtracts days, and converting to the Date data type
 -- ensures that I don't have a time component hanging around.
 set @startDate = convert(date, DateAdd(day,- DatePart(day, @someDate)   1, @someDate))

 -- I want the first day of the next month.  This is easy:
 set @endDate = DateAdd(month, 1, @startDate)

 -- Here's my actual query, that can take advantage of indexes that include DateColumn:
 select * 
 from   Table1
 where  DateColumn >= @startDate and DateColumn < @endDate
 

Обратите внимание, что я указал >= дату начала, но < для даты окончания. Это гарантирует, что я получу любые записи даты за последний день месяца, которые имеют ненулевой компонент времени, но не перейдут в следующий месяц.

Ответ №2:

Лучший способ для долгосрочного решения — создать таблицу измерений даты (вы можете найти там сценарии для ее автоматической генерации). Таблица date dim будет содержать список дат как можно дальше назад и вперед, и она включает в себя такие столбцы, как DayOfWeek, QuarterOfYear, ГГГГ и т. Д., Так что вы можете присоединить ПРИВЕДЕНИЕ (YOURDATE КАК DATE) к дате date dim и получить точную информацию о дате. Здесь вы можете присоединить обе свои таблицы к дате dim и использовать, ГДЕ t1.ГГГГ = t2.ГГГГ.