SQL Server查询优化问题

时间:2011-03-09 16:38:39

标签: sql sql-server tsql

SQL服务器似乎正在优化查询的方式导致它破坏。以下两个例子说明了这一点:

SELECT distinct ET.ElementName, ET.Shared, CONVERT(float,ED.Value), ED.SheetSetVersionID, ED.SheetDataID
FROM tElementData ED 
INNER JOIN tElementTemplate ET 
ON ED.ElementTemplateID = ET.ElementTemplateID 
AND ET.ElementName like 'RPODCQRated'

上面的查询工作正常,但不是我需要运行的查询。

SELECT distinct ET.ElementName, ET.Shared, CONVERT(float,ED.Value),    ED.SheetSetVersionID, ED.SheetDataID
FROM tElementData ED 
INNER JOIN tElementTemplate ET 
ON ED.ElementTemplateID = ET.ElementTemplateID 
AND ET.ElementName like 'RPODCQRated'
AND CONVERT(float,ED.Value) = 0.006388

上面的查询抛出一个异常,说它无法将nvarchar值转换为float。 tElementData.Value是一个nvarchar(500)字段,有些记录没有数字值,但是tElementTemplate ='RPODCQRated'的所有值都可以转换为float,正如顶层查询所证明的那样。似乎SQL服务器在尝试连接之前应用CONVERT(float,ED.Value)。我需要第二个查询才能以某种方式工作,我可以重写它,但是如果不重写现有应用程序的整个数据层,我可以做些什么。

我尝试过的事情没有帮助:将最后一个标准移动到where子句而不是连接,将第一个查询转换为CTE并将where子句应用于CTE,创建一个调用IsNumeric的标量函数尝试进行转换之前的数据。

唯一能够工作的是将所有数据插入临时表,然后将where子句应用于临时表。不幸的是,将其作为解决方案实现将涉及对应用程序的数据层进行大量重构,以便在搜索某些记录时解决一个模糊的错误。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

确保线性评估的唯一方法是使用Case Statement

SELECT distinct ET.ElementName, ET.Shared, CONVERT(float,ED.Value), ED.SheetSetVersionID, ED.SheetDataID 
FROM tElementData ED  
INNER JOIN tElementTemplate ET  
ON ED.ElementTemplateID = ET.ElementTemplateID  
AND ET.ElementName like 'RPODCQRated' 
AND CASE(WHEN ET.ElementName like 'RPODCQRated' then CONVERT(float,ED.Value) else 0 end) = 0.006388 

这可能会导致对ElementName进行重复检查,但据我所知,这是确保评估顺序的唯一方法。

当然,除非您将整个eval移出查询并将结果嵌套在CTP中并对结果进行强制转换。

答案 1 :(得分:0)

我会试着把它分解成这样的东西:

;with a as
(

SELECT distinct
    ET.ElementName,
    ET.Shared,
    CONVERT(float, ED.Value),
    ED.SheetSetVersionID,
    ED.SheetDataID
FROM
    tElementData ED
    INNER JOIN tElementTemplate ET
        ON ED.ElementTemplateID = ET.ElementTemplateID
           AND ET.ElementName like 'RPODCQRated'
)
select *
from a
where CONVERT(float, ED.Value) = 0.006388

或者,你试过“ED.Value ='0.006388'或varchar equivilent是什么?

答案 2 :(得分:0)

我通过使用表函数解决了这个问题。最后一个连接子句的元素名称,运算符和右手值都是动态生成的。我创建了下面的tvf,并通过调用tvf替换了select语句的相关部分。

CREATE FUNCTION tvfAdvancedSearch
(
    @TemplateType nvarchar(500)
)
RETURNS 
@Results TABLE 
(   
    ElementName nvarchar(50),
    Shared tinyint, 
    Value NVARCHAR(500), 
    SheetSetVersionID int, 
    SheetDataID int
)
AS
BEGIN
    INSERT INTO @Results
    SELECT distinct ET.ElementName, ET.Shared, ED.Value, ED.SheetSetVersionID, ED.SheetDataID
    FROM tElementData ED 
    INNER JOIN tElementTemplate ET 
        ON ED.ElementTemplateID = ET.ElementTemplateID 
        AND ET.ElementName like @TemplateType   
    RETURN 
END
GO

我还想提一下,Brian Rudolph的回答也有效,但在我看到他的帖子之前我已经实施了这个解决方案。