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子句应用于临时表。不幸的是,将其作为解决方案实现将涉及对应用程序的数据层进行大量重构,以便在搜索某些记录时解决一个模糊的错误。
有什么想法吗?
答案 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的回答也有效,但在我看到他的帖子之前我已经实施了这个解决方案。