WHERE子句可查找特定月份的所有记录


83

我希望能够给存储过程一个月和一年,并使其返回该月发生的所有事情,我该怎么做,因为在某些月份的天数不同等情况下我无法进行比较?

最好的方法是什么?我可以要求根据年份和月份进行比较吗?

谢谢。

Answers:


181

我认为您正在寻找的功能是MONTH(date)。您可能也想使用 “ YEAR”

假设您有一个名为的表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_at2009/01月份(2009年1月)中具有的记录。SQL查询为:

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

哪个会返回:

id
---
1
3
4

13
确实 !对于感兴趣的任何人“ DAY,MONTH和YEAR函数分别是DATEPART(dd,date),DATEPART(mm,date)和DATEPART(yy,date)的同义词。”
塔克斯

15

大多数响应中建议使用MONTH和YEAR函数的缺点是SQL Server将无法使用日期列上可能存在的任何索引。这会破坏大桌子上的性能。

我倾向于将DATETIME值(例如@StartDate)传递给表示您感兴趣的月份的第一天的存储过程。

然后,您可以使用

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

如果必须将月和年作为单独的参数传递给存储过程,则可以使用CAST和CONVERT生成代表月份第一天的DATETIME,然后按上述步骤进行。如果这样做,我建议编写一个函数,该函数根据整数的年,月,日值生成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将无法使用日期列上可能存在的任何索引。这可能会破坏大型表的性能。 。”
拉加夫2009年

我可以加些东西吗?如果您在参数中声明'@StartDate,那么我也将声明'@EndDate并将DATEADD放在此处,而不是让SQL对每一行进行数学运算。
DataGirl

@DataGirl-有趣的一点。我假设DATEADD函数将被视为运行时常量,并且仅被评估一次。如果对此有疑问,则声明@EndDate将使其明确。

3

作为MONTH和YEAR函数的替代方法,常规的WHERE子句也将起作用:

select *
from yourtable
where '2009-01-01' <= datecolumn and datecolumn < '2009-02-01'

3

一个提示很简单。您还可以使用to_char函数,如下所示:

每月:

to_char(happened_at,'MM')= 01

年份:
to_char(happened_at,'YYYY')= 2009

对于一天:

to_char(happened_at,'DD')= 01

to_char函数由sql语言而不是一个特定的数据库支持。

希望对大家有帮助...

吸收!


1
我觉得这仅适用于Oracle,这确实很具体。SQL Server绝对不支持它。
卡罗尔2015年


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)传递,然后使用时间功能(特别是DATEADDDATEPART)来找到该期间的开始日期和结束日期,在这种情况下是月份,例如,这将找到开始日期和结束日期对对于当前月份,只需替换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

一种方法是创建一个代表月份的第一天的变量(即2009年5月1日),或者将其传递到proc或进行构建(连接月份月1日/年)。然后使用DateDiff函数。

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

这将返回具有匹配的月份和年份的任何内容。


-4
SELECT * FROM yourtable WHERE yourtimestampfield LIKE 'AAAA-MM%';

AAAA您想要的年份在哪里,您想要MM的月份在哪里

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.