在查询中使用TOP 1的问题

时间:2010-09-03 09:56:34

标签: tsql select

我编写了以下查询以获取日期,删除它的时间部分并添加我想要的时间。 如果我在没有TOP子句的情况下运行此查询,则效果很好。但是当我添加它时,它会返回以下异常:“从字符串转换日期和/或时间时转换失败。”

以下是查询:

SELECT TOP 1 
CONVERT(DateTime, (CONVERT(varchar(50),CONVERT(Date, VRSAS.EventOn)) 
+ ' ' + 
CONVERT(varchar(50), CONVERT(Time, '23:30')))) E 
FROM ViewRangeSheetActualStatus VRSAS 
Where VRSAS.EventOn <= '2010-07-31' 
AND VRSAS.[Status] = 1
 order by VRSAS.RangeSheet

字段EventOn的类型为DateTime。

可能会发生什么?

3 个答案:

答案 0 :(得分:2)

我很容易再现这一目的。我发现使用DATEADD解决了它

DATEADD(MINUTE, 23*60 + 30, CONVERT(DATETIME,CONVERT(DATE, VRSAS.EventOn)))

但我现在还不确定为什么。下面重现的步骤。

CREATE TABLE ViewRangeSheetActualStatus
(EventOn DATETIME,
[Status] BIT,
RangeSheet INT
)

INSERT INTO [dbo].[ViewRangeSheetActualStatus]([EventOn], [Status], [RangeSheet])
SELECT '20100903 11:02:39.517', 1, 1 UNION ALL
SELECT '20100731 11:03:23.577', 1, 1 UNION ALL
SELECT '20100731 00:00:00.000', 1, 1

/*Selects ALL records - No error*/
SELECT 
CONVERT(DateTime, (CONVERT(varchar(50),CONVERT(Date, VRSAS.EventOn)) 
+ ' ' + 
CONVERT(varchar(50), CONVERT(Time, '23:30')))) E 
FROM ViewRangeSheetActualStatus VRSAS 

/*Selects top (1) record - Error!*/   
SELECT top (1)
CONVERT(DateTime, (CONVERT(varchar(50),CONVERT(Date, VRSAS.EventOn)) 
+ ' ' + 
CONVERT(varchar(50), CONVERT(Time, '23:30')))) E 
FROM ViewRangeSheetActualStatus VRSAS 

查看执行计划中的ComputeScalar属性,两者是不同的。

所有

(CONVERT(datetime,(CONVERT(varchar(50),CONVERT(date,[ViewRangeSheetActualStatus].
 [EventOn] as [VRSAS].[EventOn],0),0)+[@1])+CONVERT(varchar(50),CONVERT(time(7), 
 [@2],0),0),0))

排名前1

(CONVERT(datetime,(CONVERT(varchar(50),CONVERT(date,[ViewRangeSheetActualStatus].
 [EventOn] as [VRSAS].[EventOn],0),121)+' ')+'23:30:00.0000000',0))

在最终转换为datetime之前,第一个产生包含以下

的varchar
------------------------------
Sep  3 2010 11:30PM
Jul 31 2010 11:30PM
Jul 31 2010 11:30PM

第二个版本生成包含

的varchar
------------------------------
2010-09-03 23:30:00.0000000

.0000000会导致问题转回datetime。我不知道为什么在查询中添加TOP会导致这种完全不相关的行为更改。

答案 1 :(得分:2)

似乎自动参数化是造成不一致的原因。

联机丛书documents DATE,TIME,DATETIME2和DATETIMEOFFSET默认使用CONVERT样式121,而样式0用于DATETIME和SMALLDATETIME。有人忘了更新新类型的自动参数化规则:)

如果可以自动参数化查询,则如果进行隐式转换或具有指定样式的显式转换,则样式0将错误地应用于新的DATE / TIME类型。没有TOP的查询是自动参数化的(参数[@ 1]出现而不是TIME文字)。 TOP是阻止自动参数化的(许多)查询功能之一。

明显的解决方法是在使用CONVERT时始终指定所需的样式。

答案 2 :(得分:1)

一个奇怪的问题,您是否确认它确实可以解决“最重要的一个”限制?有时“顶部”只会使错误更明显。如果你有很多行,并且你删除了“前一个”限制,那么查询可能会给人一种工作的印象,但是在后台它仍然会结果并且没有点击导致问题的那一行。

EventOn是否可以为空,这可能是一个主要原因。如果是这样,请先进行非空检查。

此外,什么是“RangeSheet”类型,它是什么数据类型并且可以保留空值?