2015-02-18 2 views
0

У меня есть таблица в SQL Server, которая имеет много строк, с столбцом created_date. Этот столбец имеет ряды, начиная с 2006 года.SQL-запрос, не возвращающий все строки

Я хочу получить все строки, которые были созданы до февраля 2015 года. Эта хранимая процедура имеет параметр @month. Он должен выбрать все строки на основе введенного значения @month.

Вот мой запрос:

select * 
from products 
where 1=1 
    and year(created_date) <= 2015 
    and month(created_date) <= @month 

Но этот запрос возвращает только те записи, которые были созданы в и до февраля месяца прошлых лет за исключением записей, которые были созданы в других месяцах 2014 года (например, , 2014-03-17, 2014-05-05).

Я должен получить новую дату, основанную на введенном @month. Предположим, что я вступил в месяц в июле, я хочу иметь условие «где created_date < 2015-07-31». Так что я могу сделать что-то вроде этого,

Так что я изменил мой запрос,

declare @date datetime 
set @date = CAST((2015 + '-' + @month + '-' + 28) as datetime) 
select * 
from products 
where 1=1 
and year(created_date) <= 2015 

Но этот запрос возвращает 1905-08-08 00: 00: 00,000 и я хочу, чтобы получить 2015-02-28 00: 00: 00.000, а также я должен найти общее количество дней на основе введенного @month, чтобы я мог передать это число на CAST ((2015 + '-' + @month + '-' +) в качестве datetime) вместо 28.

+2

Просто используйте переменную даты, которая имеет значение для ограничения, которое вы хотите использовать в качестве критериев вместо использования функций year() и month()? Например. created_date <= @limit –

ответ

3

Просто используйте одну дату и указать, что created_date столбец должен быть меньше, чем эта дата:

declare @newestDate datetime = '2015-03-01' 

select * 
from products 
where created_date < @newestDate 

Обратите внимание, что я установил дата должна быть 1 марта, но в запросе я использую <, а не <=. Это будет соответствовать значению created_date, включая компонент времени, например. 2015-02-28 23:59:59

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

declare @newestDate datetime = 
    DATEADD(year, -1, DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0)) 

Это затем работайте в следующем месяце (т. е. в марте) и предложите вашему запросу месяц.

0

В этом вопросе: Create a date with T-SQL вы увидите, как построить тип данных даты sql-сервера, заданный в течение определенного года и месяца. Предположим, вы называете это «my_date».

Вы тогда будете в состоянии сделать следующее:

SELECT * FROM products WHERE created_date < my_date 
1

Всегда сравнивайте поля даты и времени с одним значением, где это возможно - это лучше всего подходит для производительности. Вы можете «круглые» даты с DATEADD и DATEDIFF.

DECLARE @startOfNextMonth DATETIME; 
SELECT @startOfNextMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0); 
select * from products where 1=1 and created_date < @startOfNextMonth; 

Управление строками для преобразования дат также возможно, но имеет тенденцию к худшему и сложно сделать правильно.Этот метод применяется в общем случае, если вы хотите «округлить» до лет, минут, 15-секундных периодов и т. Д., Что намного сложнее с помощью строк.

Если вы можете, перепишите хранимую процедуру, чтобы не принимать параметр @month, а абсолютное значение, которое рассчитывают ваши клиенты - это более общий и, как правило, легче работать. Ваш запрос, то просто сводится к

select * from products where 1=1 and created_date < @limit; 

Конечно, если вы должны использовать @month, вы можете построить это смещение в самой хранимой процедуре:

DECLARE @limit DATETIME = 
    DATEFROMPARTS(DATEPART(YEAR, GETDATE()), @month, 1) 
; 

Это использует DATEFROMPARTS, который был введен с SQL Server 2012. Для предыдущих версий надежное построение даты значительно бесполезнее. Существует много неправильных способов сделать это, что будет нарушено, если региональные настройки будут установлены на что-то неожиданное. DATEADD снова помощь:

DECLARE @limit DATETIME = 
    DATEADD(MONTH, (DATEPART(YEAR, GETDATE()) - 1900) * 12 + @month - 1, 0) 
; 

Это не единственные способы построить значения даты и время, но манипуляция строки в любом случае сложно (потому что единственный надежный формат, который не будет ломаться в соответствии с региональными настройками не YYYYMMDD, без черточки).

Смежные вопросы