#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.ГГГГ.