Ответ 1
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()))
Вам нужно проверить месяц и год.
Я хочу получить записи за последний месяц на основе поля db table [member] "date_created".
Что такое sql для этого?
Для уточнения, в прошлом месяце - с 1/8/2009 по 31/8/2009
Если сегодня 3/1/2010, мне нужно будет получить записи от 1/12/2009 до 31/12/2009.
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
), оптимизатор должен игнорировать индексы в столбце и выполнять поиск по каждой записи. Вот краткий пример:
Мы имеем дело со временными метками, и большинство РСУБД имеют тенденцию хранить эту информацию как возрастающую ценность какого-либо типа, обычно это число 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, что угодно), по существу возвращающим большое целое число. Это количество месяцев до начала текущего месяца. Затем мы добавим этот номер в начало эры, которая находится в начале данного месяца.
Таким образом, ваш полный script может/должен выглядеть примерно так:
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()))
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)
В прошлом месяце рассмотрим до последнего дня месяца. 31/01/2016 здесь последний день месяца будет 31 января, что не похоже на последние 30 дней.
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
В сервере Sql за последний месяц:
select * from tablename
where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()
WHERE
date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0)
AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
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)
Я из Oracle env, и я бы сделал это в Oracle:
select * from table
where trunc(somedatefield, 'MONTH') =
trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')
Идея: я запускаю запланированный отчет предыдущего месяца (с первого дня до последнего дня месяца, а не окна). Это может быть недобросовестным индексом, но в любом случае Oracle имеет быструю обработку даты. Есть ли простой и короткий путь в MS SQL? Ответ, сравнивающий год и месяц отдельно, кажется глупым для людей Oracle.
Вы можете получить записи последнего месяца с этим запросом
SELECT * FROM dbo.member d WHERE CONVERT (DATE, date_created, 101) >= CONVERT (DATE, DATEADD (m, dateiff (m, 0, current_timestamp) -1, 0)) и CONVERT (DATE, date_created, 101) < CONVERT (DATE, DATEADD (m, dateiff (m, 0, current_timestamp) -1, 0), 101)