Пункт WHERE, щоб знайти всі записи за певний місяць


87

Я хочу мати можливість дати збереженій процедурі місяць і рік і повернути все, що відбувається в цьому місяці. Як це зробити, оскільки я не можу порівняти між собою, оскільки деякі місяці мають різну кількість днів тощо?

Який найкращий спосіб це зробити? Чи можу я просто попросити порівняти виходячи з року та місяця?

Дякую.

Відповіді:


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
Справді! Для всіх, кого цікавить: "Функції DAY, MONTH та YEAR є синонімами DATEPART (dd, date), DATEPART (mm, date) та 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 "Використання функцій МІСЯЦЬ та РІК, як пропонується у більшості відповідей, має той недолік, що SQL Server не зможе використовувати будь-який індекс, який може бути у стовпці вашої дати. Це може погіршити продуктивність великої таблиці . "
Raghav

Чи можу я щось додати? Якщо ви оголошуєте '@StartDate у параметрі, я б також оголосив' @EndDate і помістив туди DATEADD, а не щоб SQL обчислював у кожному рядку.
DataGirl

@DataGirl - цікавий момент. Я припускав, що функція DATEADD буде розглядатися як константа виконання і обчислюватися лише один раз. Якщо в цьому є сумніви, декларування @EndDateзробить це явним.
Джо

4

Ще одна порада дуже проста. Ви також можете використовувати функцію to_char , подивіться:

За місяць:

to_char (відбулось_at, 'MM') = 01

Для року:
to_char (відбулось_at, 'РРРР') = 2009

На день:

to_char (відбулось_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.


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

Це поверне будь-що з відповідними місяцем та роком.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.