SQL当日期存储为nvarchar时,选择日期范围之间的所有数据

时间:2016-08-17 18:52:45

标签: sql sql-server vba sql-server-2008 date

我继承了一个包含<tab>Start_Date列的End_Date数据类型的T-SQL表。我需要选择特定日期的所有记录,其开始日期是在该日期之前,但在该日期之后有结束日期。

另一个问题是有些人仍然是最新的,没有nvarchar。遗憾的是,我不能只将列的数据类型转换为日期。我试图在VBA中写这个,因为

  1. 我的老板理解Excel,
  2. 他正在做的报告必须以Excel格式发送
  3. 例如:

    end_date

    如果我选择的日期是2015年8月15日,我的返回数据应为

    Name    Start_Date    End_Date
    Joe     12/1/2014     6/15/2016
    Bob     8/28/2013     6/5/2014
    Jon     1/27/2015     12/18/2015
    Tim     8/28/2013     
    

    我已尝试过以下查询,但他们会返回Name Start_Date End_Date Joe 12/1/2014 6/15/2016 Jon 1/27/2015 12/18/2015 Tim 8/28/2013

    Run-time error -2147217900 (80040e14) Automation error

    编辑: 我使用以下代码构造我的查询:

    SELECT NAME 
    FROM INFORMATION 
    WHERE CONVERT(datetime, START_DATE, 101) >= '12/1/2015' 
      AND CONVERT(datetime, END_DATE, 101) <= '12/31/2015'
    
    SELECT NAME 
    FROM INFORMATION 
    WHERE START_DATE >= '12/1/2015'
    

    更新2:

    我将For intYear = Year(Now()) To 2012 Step -1 For intMonth = 12 To 1 Step -1 FirstDayOfMonth = DateSerial(intYear, intMonth, 1) LastDayOfMonth = DateSerial(intYear, intMonth + 1, 0) SQL = "SELECT NAME FROM dbo.INFORMATION " & _ "WHERE CONVERT(DATETIME, START_DATE, 101) <= " & FirstDayOfMonth & " AND " & _ "CASE END_DATE WHEN '' THEN GETDATE() " & _ "ELSE CONVERT(DATETIME, END_DATE, 101) END >= " & LastDayOfMonth Debug.Print SQL 'Output: 'SELECT NAME FROM dbo.INFORMATION WHERE CONVERT(DATETIME, START_DATE, 101) '<= 12/1/2016 AND CASE END_DATE WHEN '' THEN GETDATE() ELSE 'CONVERT(DATETIME, END_DATE, 101) END >= 12/31/2016 Set rs = cn.Execute(SQL) Next intMonth Next intYear 设置为文字查询,而不是动态生成它并放入错误捕获(我很久以前就应该这样做)。我认为在日期周围加上单引号会使它成为字符串而不是日期,但我尝试了两种方式。

    SQL

    使用和不使用单引号SSMS的实际SQL错误是:

    SQL = "SELECT EMPLOYEE_NAME FROM dbo.INFORMATION " & _
          "WHERE CONVERT(DATETIME, START_DATE, 101) <= 12/01/2016 " & _
          "AND CASE END_DATE " & _
          "WHEN '' THEN GETDATE() " & _
          "ELSE CONVERT(DATETIME, END_DATE, 101) " & _
          "END >= 12/31/2016"
    

    查看表格中的数据,我可以看到有些日期是NULL,有些是空白,有些是mm / dd / yy(甚至是m / d / yy)。我希望SQL能够完成所有繁重的工作,但是现在我想确定Msg 241, Level 16, State 1, Line 4 Conversion failed when converting date and/or time from character string. 是否会更难对付它并在Excel中处理它或者让我的老板,他的同事和我的祖父与我联系#39;固定&#39;桌子。

1 个答案:

答案 0 :(得分:2)

您需要切换&gt; =和&lt; =。现在,您正在寻找在目标日期之后的开始日期和结束日期之前的人。但我认为这只是你的例子中的一个错字。

但你走在正确的轨道上。如果你想在VBA中这样做,我会警告不要在VBA中做任何逻辑。在SQL中进行所有过滤,只需使用VBA来调用SQL。另外,不要忘记您可以将Excel直接连接到SQL作为数据源并跳过VBA。

无论如何,您的SQL查询应该如下所示:

SELECT  Name
FROM    dbo.INFORMATION
WHERE   CONVERT(DATETIME, Start_Date, 101) <= @targetdate
        AND CONVERT(DATETIME, End_Date, 101) >= @targetdate

但是你有一个没有结束日期的人的情况。让我们解决它所以它都适合一个查询。

SELECT  Name
FROM    dbo.INFORMATION
WHERE   CONVERT(DATETIME, Start_Date, 101) <= @targetdate
                    AND     CASE End_Date
                              WHEN '' THEN GETDATE()
                              ELSE CONVERT(DATETIME, End_Date, 101)
                            END >= @targetdate

如果他们有结束日期,我们会使用他们的结束日期,如果他们没有,我们现在就使用它们。如果您的目标日期可能在将来,那么您可以使用任意大的日期。

最后一项是使用BETWEEN:

使其更具可读性
SELECT  Name
FROM    dbo.INFORMATION
WHERE   @targetdate BETWEEN CONVERT(DATETIME, Start_Date, 101)
                    AND     CASE End_Date
                              WHEN '' THEN GETDATE()
                              ELSE CONVERT(DATETIME, End_Date, 101)
                            END