2014-04-23 45 views
0

当我正在写将生成每周报告SQL:获得不同的结果,使用日期转换功能

查询看起来像这样的查询:

DECLARE @rundate DATETIME 
DECLARE @oneweekago AS DATETIME 

SELECT @rundate = getdate() - 2 
SELECT @oneweekago = DATEADD(week, -1,@rundate) 

SELECT 
    d.date, t2.column1, t1.column2, t1.column3 
FROM 
    table1 t1 WITH (NOLOCK) 
INNER JOIN 
    table2 t2 ON t1.id = t2.id 
INNER JOIN 
    table3 t3 WITH (NOLOCK) ON t3.id = t1.id 
INNER JOIN 
    table4 t4 WITH (NOLOCK) ON t4.id = t1.id 
INNER JOIN 
    table5 t5 WITH (NOLOCK) ON t5.num = i.num 
LEFT OUTER JOIN 
    table6 t6 WITH (NOLOCK) ON t6.intmid = t1.intmid 
WHERE 
    t2.code = '027' 
    AND t2.status in('O', 'OPEN', 'P', 'PEND', 'PENDING', 'R', 'REOPEN') 
    AND t3.odate BETWEEN @oneweekago AND @rundate 
    AND CONVERT(varchar, t3.odate, 101) BETWEEN CONVERT(varchar, @oneweekago, 101) AND CONVERT(varchar, @rundate, 101) 
ORDER BY 
    t1.column1 

当使用

CONVERT(varchar, t3.odate, 101) BETWEEN CONVERT(varchar, @oneweekago, 101) AND CONVERT(varchar, @rundate, 101) 

该查询为我提供了2009年,2011年,2010年的日期,当时我只指定了04/14/2014 - 04/21/2014(2天前的一周前)的日期。

然而,当我使用

t3.odate BETWEEN @oneweekago AND @rundate 

我得到正确的结果。

使用CONVERT方法时出错?

感谢

+0

为什么在列为DATETIME时使用该方法? – Lamak

+3

另外,对不起,不能评论一些事情。你应该**总是**使用varchar的长度('CONVERT(varchar(10),col,101)'),否则你会得到一些令人讨厌的惊喜。除此之外,您用于转换日期的格式不应与'BETWEEN'一起使用;因为你现在正在比较**串**,在这种情况下'04/14/2009'比“04/13/2014”更大。最后,如果你的专栏有'time'部分,那么你应该使用'BETWEEN',无论如何,你可以过滤比你想象的更多的结果(使用开放范围代替:> = somedate和 Lamak

+2

You won'在OneWeekAgo和RunDate之间必须始终得到正确的结果。对于日期时间,更可靠的方法是datefield> = StartDate和datefield

回答

0

你转换datetime值为varchar,它比较了不同。 SQL知道如何正确比较datetime值......没有理由做一个转换为varchar做比较。如果您需要放弃时间部分,则可以进行转换以仅获取日期,但在进行比较之前将其转换回日期格式以获得预期结果。

+1

在最近的SQL Server版本中,你可以投日期时间为日期,而不是转换回的并且。 –

+0

太棒了。感谢您的信息! :) – John

0

要转换为varchar - 转换为varchar往往可以给你意想不到的结果,因为它没有治疗的日期,如果他们是日期。它将其视为一个字符串。而当你简单地将结果作为日期时,它会正确地比较日期。如果您需要删除时间部分,则只需转换日期即可:

convert(date, @rundate, 101)