SQL Cast之谜

时间:2009-03-24 21:09:19

标签: sql-server tsql

我对下面的T-SQL有一个真正的谜。实际上,它适用DATAP.Private=1cast as int上的Right(CRS,1)。也就是说,如果我取消注释DATAP.Private=1,我会收到错误Conversion failed when converting the varchar value 'M' to data type int,如果我删除该转换,则查询会再次生效。使用强制转换后,查询仅在没有Private=1的情况下生效。

我不能为我的生活看到Private=1如何添加任何会导致错误的结果集,除非Private永远是'M',但是Privatebit字段!

SELECT 
      cast(Right(CRS,1) as int) AS Company
    , cast(PerNr as int) AS PN
    , Round(Sum(Cost),2) AS Total_Cost
FROM 
    DATAP 
    LEFT JOIN BU_Summary ON DATAP.BU=BU_Summary.BU
WHERE 
    DATAP.Extension Is Not Null 
    --And DATAP.Private=1
    And Left(CRS,2)='SB'
    And DATAP.PerNr Between '1' And '9A'
    and Right(CRS,1) <> 'm'
GROUP BY 
      cast(Right(CRS,1) as int)
    , cast(PerNr as int)
ORDER BY 
    cast(PerNr as int)

3 个答案:

答案 0 :(得分:2)

我过去见过这样的事情。 DATAP.Private = 1子句可能会生成一个在应用Right(CRS,1) <> 'm'过滤器之前执行CRS强制转换的查询计划。

肯定不应该这样做,但我在编写的T-SQL中遇到过类似的问题,特别是涉及到视图时。

您可以重新排序元素以使查询起作用,或者将未播放的数据值选择到临时表或表变量中,然后从单独的语句中选择并转换为权宜之计。

如果您检查执行计划,它可能会对计算的位置有所了解。这可能会为您提供更多关于您可能会改变的想法。

答案 1 :(得分:0)

只是一个猜测,但可能是当Private = 1时,PerNr不能是数据中的任何可转换数字(因为它在PerNr中可以等于'9A [或其他任何]',打破了分组和按条款排序)。

答案 2 :(得分:0)

CAST('9A'AS int)在我测试时失败了。看起来你正在为分组和排序做不必要的CASTS。特别是在GROUP BY中,这至少会扼杀任何优化机会。