代码之家  ›  专栏  ›  技术社区  ›  aesdanae

在MS SQL/SQL Server 2005中精确限制日期范围

  •  2
  • aesdanae  · 技术社区  · 16 年前

    我想限制报告返回从日期a到日期B的记录。这是我一直在做的事情:

    declare @startDate varchar(20)
    declare @endDate varchar(20)
    set @startDate = '01/01/2008'
    set @endDate = '04/01/2008'
    -- test what are the start and end dates
    select min(date),max(date) from view_Inspections 
    where date between @startDate and @endDate
    

    …我被告知返回了从1月1日上午12点到3月31日晚上11:59的记录(当没有显示时间时,默认为午夜)。但我注意到了一个差异,即如果一条记录的时间为00:00:00,它将成为这组记录的一部分。

    是否有更精确的方法可以做到这一点,这样它就能准确地返回我想要的日期范围*

    我试着利用时间:

    declare @startDate varchar(20)
    declare @endDate varchar(20)
    set @startDate = '01/01/2008 00:00:00'
    set @endDate = '04/01/2008 11:59:59'
    -- test what are the start and end dates
    select min(date),max(date) from view_Inspections 
    where date between @startDate and @endDate
    

    …但我注意到了一些不稳定的地方:SQL Server将把第100秒的时间缩短一半。所以,如果我在11:59:29之后的任何时间使用,我就会得到4月1日的记录(哈!愚人节记录!grr)。为什么?

    • (我确信有。我是新手。谢谢你的帮助!)
    5 回复  |  直到 16 年前
        1
  •  5
  •   Rowland Shaw    16 年前

    总有一个简单的选择:

    declare @startDate varchar(20)
    declare @endDate varchar(20)
    set @startDate = '01/01/2008'
    set @endDate = '04/01/2008'
    
    -- test what are the start and end dates
    select min(date),max(date) from view_Inspections 
    where date >= @startDate 
    and   date < @endDate
    
        2
  •  2
  •   George Mastros    16 年前

    我怀疑view_Inspections中的日期列是SmallDateTime数据类型。此数据类型的精度为1分钟,这解释了您的意外结果(将秒四舍五入到最接近的分钟)。

    Roland Shaw建议的方法是修改查询以适应您的要求的最佳方式。

        3
  •  1
  •   Tom H zenazn    16 年前

    BETWEEN运算符是包容性的,这就是为什么您在第一个查询中看到的结果。您在第二个查询中看到的舍入将取决于您在表中使用的确切日期时间数据类型。(顺便说一句,我认为你把秒和百分之一秒混淆了)。看起来你可能在表中使用了一个小日期时间,在这种情况下,时间会四舍五入到最接近的分钟。

    如果您的表使用datetime,请尝试将@startDate和@endDate显式转换为datetime值(CAST(@endDate为datetime))。

    一个简短的便条。..即使对于DATETIME值,SQL Server也只能精确到3/100秒,因此11:59:59.999将四舍五入到12:00:00.000。

    你基本上有三个选择:

    1) 在转换(日期时间为'01/01/2008 00:00:00.000')和转换(日期日期时间为'03/31/2008 12:59:59.997')之间

    2) 年份(my_date)=2008年,月份(my_dade)介于1和3之间

    3) my_date>=CAST(日期时间为2008年1月1日00:00:00.000)和my_date<演员阵容(日期时间为'04/01/2008 00:00:00.000')

    第一种方法不是很直观,在我看来很容易出错。第二种方法会扼杀性能,因为不能使用索引,而且如果搜索可以跨越数年或在月中开始/结束,则会变得更加复杂。罗兰建议的第三种方法是我认为最好的。

        4
  •  1
  •   Mutix question    13 年前

    只需尝试从日期字段中删除时间,如下所示:

    declare @startDate varchar(20)
    declare @endDate varchar(20)
    set @startDate = '01/01/2008'
    set @endDate = '04/01/2008'
    
    SELECT min(date),max(date) FROM view_Inspections 
    WHERE CAST(FLOOR(CAST(date AS FLOAT)) AS DATETIME) BETWEEN CAST(@startDate AS DATETIME) And CAST(@startDate AS DATETIME))
    

    这将返回从 01/01/2008 00:00:00 04/01/2008 11:59:59.999 . 如果你不想 04/01 包括在内,将结束日期更改为 03/31/2008 .

        5
  •  0
  •   user2242007    12 年前

    最好的解决方案是创建一个名为“julian”的BIGINT(10)字段,并将其存储在YYYYMMDD中。

    然后进行查询 其中julian>='20120103'和朱利安<= '20120203'