【问题标题】:SQL WHERE query on date rangeSQL WHERE 查询日期范围
【发布时间】:2012-01-11 14:02:14
【问题描述】:

在我的表格中,我有 118 条详细记录项目的记录。我在这里关心的 2 个字段是 startdate 和 enddate。

我需要从此视图生成一份报告,显示在以下日期范围内哪些项目处于“活跃”状态:

01/01/2011 - 01/12/2011

我尝试了以下 WHERE 类:

WHERE startdate BETWEEN '01/04/2011' AND '01/12/2011' 
OR enddate BETWEEN '01/04/2011' AND '01/12/2011'
OR startdate <= '01/04/2011' AND enddate >= '01/12/2011'

出现的情况似乎不正确,只显示了几条记录,而我知道应该显示的许多记录不是,例如一个项目的开始日期为 20/07/2011 和结束日期为 21运行 WHERE 查询时 /11/2011 消失。

任何人都可以看到这个 WHERE 查询的错误

【问题讨论】:

  • 愚蠢的问题,但是 startdate 和 enddate 的数据类型是什么?
  • 使用 VARCHAR 将格式转换为文本:convert(VARCHAR,dbo.tbl_project_data.startdate, 103) AS startdate, convert(VARCHAR,dbo.tbl_project_data.enddate, 103) AS enddate,
  • 表中的底层数据类型是什么?不是您将其转换为的基本类型? SELECT ISC.TABLE_SCHEMA, ISC.TABLE_NAME, ISC.COLUMN_NAME, ISC.DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS ISC WHERE ISC.column_name IN ('startdate', 'enddate')
  • 请记住,SQL 将时间存储为日期的一部分,因此如果您使用 GetDate() 或类似方法来填充字段值,那么还有一个时间部分。 2011 年 1 月 12 日被视为 2011 年 1 月 12 日午夜。如果在 1 月 12 日上午 10:00 使用 Getdate() 填充了日期字段,则它不会出现在查询中。
  • 我不知道,但格式是这样的:2008-01-02 00:00:00.000

标签: sql sql-server syntax reporting-services where-clause


【解决方案1】:

查询前添加

set dateformat dmy

也可以加一些括号

WHERE 
(startdate BETWEEN '01/01/2011' AND '01/12/2011')
OR 
(enddate BETWEEN '01/01/2011' AND '01/12/2011')
OR 
(startdate <= '01/01/2011' AND enddate >= '01/12/2011')

【讨论】:

  • 当我对完全不同的数据执行此操作时,我得到了 600 多条记录
  • 抱歉这是英国格式 01/01/2011 表示 1st Jan 11 和 01/12/2011 表示 1st Dec 11
【解决方案2】:
WHERE
    startdate <= '2011-12-01'
AND enddate   >= '2011-01-01'

(假设 enddate 中的值是项目活动的最后日期)

使用数字的示例,搜索与 100 到 200 重叠的任何内容...

Start | End | Start <= 200 | End >= 100

 000  | 099 |  Yes         | No
 101  | 199 |  Yes         | Yes     (HIT!)
 201  | 299 |  No          | Yes
 000  | 150 |  Yes         | Yes     (HIT!)
 150  | 300 |  Yes         | Yes     (HIT!)
 000  | 300 |  Yes         | Yes     (HIT!)

这在逻辑中绝对需要一个 AND :)


就您的查询而言...

带括号的查询看起来像这样...

WHERE
  (
     startdate BETWEEN '01/04/2011' AND '01/12/2011'
  OR enddate   BETWEEN '01/04/2011' AND '01/12/2011'
  OR startdate <= '01/04/2011'
  )
  AND enddate >= '01/12/2011'

但是您的示例永远不会满足最后一个 AND 条件。尝试添加括号更明确...

WHERE
     (startdate BETWEEN '01/04/2011' AND '01/12/2011')
  OR (enddate   BETWEEN '01/04/2011' AND '01/12/2011')
  OR (startdate <= '01/04/2011' AND enddate >= '01/12/2011')

【讨论】:

  • 有些项目于 2009 年开始,预计于 2013 年结束
  • 我也会这样做,因为 SQL Server 总是使用这种格式并且是国际标准。
  • @SQL_Surfer - 我的第一个示例也适用于这些。有 6 个基本场景(全部在您的范围之前)(与您的范围开始重叠)(全部在您的范围内)(与范围结束重叠)(全部在您的范围之后)(与整个范围重叠)。两行检查适用于所有 6 种情况。
【解决方案3】:

假设startdateenddate 是日期字段,

试试这个:

WITH Dates AS ( 
      SELECT [Date] = @StartDate
      UNION ALL SELECT [Date] = DATEADD(DAY, 1, [Date])
      FROM Dates WHERE [Date] <= DATEADD(DAY, -1, @EndDate)
) 
-- YOUR SELECT STATEMENT
-- YOUR FROM STATEMENT
CROSS APPLY Dates
WHERE [Date] BETWEEN startdate AND enddate 
-- The rest of your where statement here
OPTION(MAXRECURSION 0);

将开始日期声明为01/01/2011,将结束日期声明为01/12/2011

【讨论】:

    【解决方案4】:

    当您可以将字符串与列进行比较时,将 startdate 和 enddate 与字符串进行比较时,每个人都以错误的方式看待这个问题;以下是确定您想要什么的最简单方法:

    where ( '01/04/2011' between startdate and enddate
              or  '01/12/2011' between startdate and enddate
             )
    

    【讨论】:

      【解决方案5】:

      我的原始查询正在运行,但我连接的数据库与我的查询有不同的日期格式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多