Предложение WHERE для поиска всех записей за определенный месяц

87

Я хочу иметь возможность дать хранимой процедуре месяц и год и вернуть все, что происходит в этом месяце, как мне это сделать, поскольку я не могу сравнивать, поскольку в некоторых месяцах разное количество дней и т. Д.?

Как лучше всего это сделать? Могу я просто попросить сравнить по году и месяцу?

Благодарю.

Tarks
источник

Ответы:

186

Я думаю, что функция, которую вы ищете MONTH(date). Вы, вероятно, тоже захотите использовать "ГОД" .

Предположим, у вас есть таблица с именем, thingsкоторое выглядит примерно так:

id happend_at
-- ----------------
1  2009-01-01 12:08
2  2009-02-01 12:00
3  2009-01-12 09:40
4  2009-01-29 17:55

happened_atДопустим, вы хотите выполнить, чтобы найти все записи, у которых есть в течение месяца 2009/01 (январь 2009 г.). Запрос SQL будет таким:

SELECT id FROM things 
   WHERE MONTH(happened_at) = 1 AND YEAR(happened_at) = 2009

Что вернется:

id
---
1
3
4
Шалом Краймер
источник
14
Конечно ! Для всех, кто интересуется: «Функции ДЕНЬ, МЕСЯЦ и ГОД являются синонимами DATEPART (дд, дата), DATEPART (мм, дата) и DATEPART (yy, date) соответственно».
Tarks
17

Использование функций МЕСЯЦ и ГОД, как предлагается в большинстве ответов, имеет тот недостаток, что SQL Server не сможет использовать какой-либо индекс, который может быть в вашем столбце даты. Это может снизить производительность на большом столе.

Я был бы склонен передать значение DATETIME (например, @StartDate) в хранимую процедуру, которая представляет первый день интересующего вас месяца.

Затем вы можете использовать

SELECT ... FROM ...
WHERE DateColumn >= @StartDate 
AND DateColumn < DATEADD(month, 1, @StartDate)

Если вы должны передать месяц и год как отдельные параметры в хранимую процедуру, вы можете сгенерировать DATETIME, представляющую первый день месяца, с помощью CAST и CONVERT, а затем действуйте, как указано выше. Если вы сделаете это, я бы рекомендовал написать функцию, которая генерирует DATETIME из целых значений года, месяца, дня, например, следующее из блога SQL Server .

create function Date(@Year int, @Month int, @Day int)
returns datetime
as
    begin
    return dateadd(month,((@Year-1900)*12)+@Month-1,@Day-1)
    end
go

Тогда запрос становится:

SELECT ... FROM ...
WHERE DateColumn >= Date(@Year,@Month,1)
AND DateColumn < DATEADD(month, 1, Date(@Year,@Month,1))
Джо
источник
1
Я согласен с @joe "Использование функций MONTH и YEAR, как предлагается в большинстве ответов, имеет тот недостаток, что SQL Server не сможет использовать какой-либо индекс, который может быть в вашем столбце даты. Это может убить производительность на большой таблице . "
Raghav
Могу я что-нибудь добавить? Если вы объявляете @StartDate в параметре, я бы также объявил @EndDate и поместил туда DATEADD, вместо того, чтобы SQL выполнял математические вычисления в каждой строке.
DataGirl
@DataGirl - интересный момент. Я предполагал, что функция DATEADD будет рассматриваться как константа времени выполнения и оцениваться только один раз. Если в этом есть сомнения, декларация @EndDateсделает это явным.
Джо
4

Еще один совет очень простой. Вы также можете использовать функцию to_char , посмотрите:

На месяц:

to_char ( could_at , 'MM') = 01

На год:
to_char ( could_at , 'ГГГГ') = 2009 г.

На день:

to_char ( could_at , 'DD') = 01

Функция to_char поддерживается языком sql, а не одной конкретной базой данных.

Я надеюсь помочь кому-нибудь еще ...

Абс!

Марсело Ребусас
источник
1
У меня такое впечатление, что это работает только для Oracle, это действительно специфично. SQL Server определенно не поддерживает его.
Кэрол
3

В качестве альтернативы функциям MONTH и YEAR также будет работать обычное предложение WHERE:

select *
from yourtable
where '2009-01-01' <= datecolumn and datecolumn < '2009-02-01'
Андомар
источник
2

Если вы используете SQL Server, загляните в DATEPART.

http://msdn.microsoft.com/en-us/library/ms174420(SQL.90).aspx

DATEPART (мм, [ДАТА, НА КОТОРОЙ ВЫ СМОТРИТЕ])

Затем вы можете использовать с ним обычную целочисленную логику. То же самое для года, просто используйте yy вместо mm.

Gromer
источник
1

Могу я просто попросить сравнить по году и месяцу?

Вы можете. Вот простой пример с использованием образца базы данных AdventureWorks ...

DECLARE @Year       INT
DECLARE @Month      INT

SET @Year = 2002
SET @Month = 6

SELECT 
    [pch].* 
FROM 
    [Production].[ProductCostHistory]   pch
WHERE
    YEAR([pch].[ModifiedDate]) = @Year
AND MONTH([pch].[ModifiedDate]) = @Month
Ленивый администратор базы данных
источник
1

Мне легче передать значение как временный тип данных (например DATETIME), а затем использовать временные функции, в частности, DATEADDи DATEPARTнайти даты начала и окончания периода, в данном случае месяц, например, это находит пару даты начала и даты окончания для текущего месяца просто замените свой CURRENT_TIMESTAMPпараметр типа DATETIME(обратите внимание, что значение 1990-01-01 совершенно произвольно):

SELECT DATEADD(M, 
          DATEDIFF(M, '1990-01-01T00:00:00.000', CURRENT_TIMESTAMP), 
          '1990-01-01T00:00:00.000'), 
       DATEADD(M, 
          DATEDIFF(M, '1990-01-01T00:00:00.000', CURRENT_TIMESTAMP), 
          '1990-01-31T23:59:59.997')
один день, когда
источник
0

Что-то вроде этого должно сработать:

select * from yourtable where datepart(month,field) = @month and datepart(year,field) = @year

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

Иэн

Храм
источник
0

Один из способов - создать переменную, представляющую первое число месяца (т.е. 5/1/2009), либо передать ее в процесс, либо построить (объединить месяц / 1 / год). Затем используйте функцию DateDiff.

WHERE DateDiff(m,@Date,DateField) = 0

Это вернет что-нибудь с соответствующим месяцем и годом.

Майк Беннетт
источник
-4
SELECT * FROM yourtable WHERE yourtimestampfield LIKE 'AAAA-MM%';

Где AAAAгод, который вы хотите, и MMкакой месяц вы хотите

user2022742
источник