Получение записей за последний месяц в SQL server
Я хочу получить записи за последний месяц на основе моего поля db table [member]"date_created".
Что такое sql для этого?
для уточнения, последний месяц-с 1/8/2009 по 31/8/2009
Если сегодня 3/1/2010, мне нужно будет получить записи с 1/12/2009 по 31/12/2009.
17 ответов:
SELECT * FROM Member WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate())) AND DATEPART(yyyy, date_created) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
нужно проверить месяц и год.
все существующие (работа) ответы имеют одну из двух проблем:
- они будут игнорировать индексы в столбце при поиске
- воля (потенциально) выбирает данные, которые не предназначены, молча разрушая ваши результаты.
1. Игнорируемые Индексы:
по большей части, когда искомый столбец имеет функцию, вызываемую на нем (в том числе неявно, например, для
CAST
), оптимизатор должен игнорировать индексы на колонке и поиск по каждой записи. Вот краткий пример:мы имеем дело с метками времени, и большинство РСУБД, как правило, хранят эту информацию в виде возрастающего значения какого-то типа, обычно a
long
илиBIGINTEGER
количество миллисекунд / наносекунд. Текущее время таким образом выглядит/хранится следующим образом:1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
вы не видите значение "год" (
'2014'
) там, не так ли? На самом деле, есть довольно сложная математика для перевода туда и обратно. Так что если вы вызываете любую из функций извлечения / даты в столбце поиска, сервер должен выполнить всю эту математику, чтобы выяснить, можно ли включить ее в результаты. В небольших таблицах это не проблема, но по мере уменьшения процента выбранных строк это становится все большим и большим утечкой. Тогда в этом случае, вы делаете это во второй раз спрашиваю оMONTH
... ну, вы поняли картину.2. Непреднамеренные данные:
в зависимости от конкретная версия SQL Server и типы данных столбцов, используя
BETWEEN
(или аналогичные включительные диапазоны верхней границы:<=
)может привести к неправильному выбору данных. По сути, вы потенциально можете включить данные с полуночи " следующего "дня или исключить некоторую часть записей" текущего " дня.что ты должны делаем:
поэтому нам нужен способ, который безопасен для наших данных, и будет использовать индексы (если жизнеспособный.) Правильный путь тогда имеет вид:
WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth
учитывая, что есть только один месяц,
@startOfPreviousMonth
может быть легко заменен на/выведен:DATEADD(month, -1, @startOCurrentfMonth)
Если вам нужно вывести начало текущего месяца на сервере, вы можете сделать это с помощью следующего:
DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
краткое объяснение здесь. Начальная
DATEDIFF(...)
получит разницу между началом текущей эпохи (0001-01-01
- AD, CE, что угодно), по существу возвращая большой целое число. Это количество месяцев до начала настоящее месяц. Прибавим это число к началу эпохи, которая находится в начале данного месяца.таким образом, ваш полный скрипт может / должен выглядеть следующим образом:
DECLARE @startOfCurrentMonth DATETIME SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0) SELECT * FROM Member WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally misspelled AND date_created < @startOfCurrentMonth
таким образом, все операции с датами выполняются только один раз, на одном значении; оптимизатор может свободно использовать индексы, и никакие неправильные данные не будут включены.
добавить параметры, которые были предоставлены до сих пор не будет использовать ваши индексы на всех.
что-то вроде этого будет делать трюк, и использовать индекс в таблице (если он существует).
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = dateadd(mm, -1, getdate()) SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate) SET @EndDate = dateadd(mm, 1, @StartDate) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0) SET @EndDate = DATEADD(mm, 1, @StartDate) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
обновление до решения mrdenny, таким образом, вы получите ровно в прошлом месяце от YYYY-MM-01
один из способов сделать это с помощью DATEPART функция:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = 4 and DATEPART(year, date_created) = 2009
вернет все даты в апреле. За последний месяц (т. е. до текущего месяца) вы можете использовать GETDATE и DATEADD а также:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = (DATEPART(month, GETDATE()) - 1) and DATEPART(year, date_created) = DATEPART(year, DATEADD(m, -1, GETDATE()))
последний месяц считать до последнего дня месяца. 31/01/2016 здесь последний день месяца будет 31 января. который не похож на последние 30 дней.
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
select * from [member] where DatePart("m", date_created) = DatePart("m", DateAdd("m", -1, getdate())) AND DatePart("yyyy", date_created) = DatePart("yyyy", DateAdd("m", -1, getdate()))
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0) SET @EndDate = dateadd(dd, -1, DATEADD(mm, 1, @StartDate)) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
и еще одно обновление до решения mrdenny.
Это дает точный последний день предыдущего месяца.
declare @PrevMonth as nvarchar(256) SELECT @PrevMonth = DateName( month,DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)) + '-' + substring(DateName( Year, getDate() ) ,3,4)
SQL запрос, чтобы получить запись только за текущий месяц
SELECT * FROM CUSTOMER WHERE MONTH(DATE) = MONTH(CURRENT_TIMESTAMP) AND YEAR(DATE) = YEAR(CURRENT_TIMESTAMP);
в Sql server за последний месяц:
select * from tablename where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()
DECLARE @curDate INT = datepart( Month,GETDATE()) IF (@curDate = 1) BEGIN select * from Featured_Deal where datepart( Month,Created_Date)=12 AND datepart(Year,Created_Date) = (datepart(Year,GETDATE())-1) END ELSE BEGIN select * from Featured_Deal where datepart( Month,Created_Date)=(datepart( Month,GETDATE())-1) AND datepart(Year,Created_Date) = datepart(Year,GETDATE()) END
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = dateadd(mm, -1, getdate()) SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate) SET @EndDate = dateadd(mm, 1, @StartDate) set @StartDate = DATEADD(dd, 1 , @StartDate)
WHERE date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0) AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
Я из Oracle env, и я бы сделал это так в Oracle:
select * from table where trunc(somedatefield, 'MONTH') = trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')
идея: я запускаю запланированный отчет предыдущего месяца (от дня 1 до последнего дня месяца, не оконный). Это может быть индекс недружественным, но Oracle имеет быструю обработку даты в любом случае. Есть ли подобный простой и короткий путь в MS SQL? Ответ, сравнивающий год и месяц отдельно, кажется глупым людям Oracle.