这是我的sql
SELECT * FROM Answers
WHERE QuesID = 1 AND OptionID IN (2,5) AND CONVERT(float, ISNULL(AnswerValue, 0)) < 300
问题是遗留数据是OptionID = 6中的字符串。当我运行上面的查询时,它给了我
将数据类型varchar转换为float时出错。
我确认了QuesID = 1中的所有数据,而OptionId IN(2,5)中的所有数据都是浮点数据。看起来SQL首先在做这个sql的数学部分,无论如何要在运行AnswerValue比较之前检查OptionID吗?还是我完全偏离基地?
答案 0 :(得分:3)
您无法真正控制SQL将“解析”WHERE
子句中的子句的顺序。我做了一些快速测试,如果只为QuesId = 3输入了一个字符串值,那就可以了。
所以,是的,正如你在我写这篇文章时发布的那样,扔进去了
AND isnumeric(AnswerValue) = 1
将处理此问题,因为SQL似乎在其过程的早期对其进行了评估。
答案 1 :(得分:1)
想出来,我刚刚将SQLNUMERIC添加到SQL中并对其进行了排序。
答案 2 :(得分:1)
如果搜索到的条件匹配,CASE
表达式将仅评估其结果表达式,因此您可以尝试:
SELECT * FROM Answers
WHERE
CASE WHEN QuesID = 1 AND OptionID IN (2,5) THEN
CONVERT(float, ISNULL(AnswerValue, 0))
ELSE
500
END < 300
对于更复杂的表达式,您可以选择使用嵌套的CASE
表达式来执行更多逻辑 - 通常,这将导致您表达所有条件并使结果等于0
或{ {1}},然后执行与1
的最终外部比较:
1
WHERE
1 = CASE WHEN <Condition 1> THEN
CASE WHEN <Condition 1, Subcondition 1> THEN 0
WHEN <Condition 1, Subcondition 2> THEN 1
END
WHEN <Condition 2> THEN
CASE WHEN <Condition 2, Subcondition 1> THEN 1
WHEN <Condition 2, Subcondition 2> THEN 0
END
END
的两个子条件仅在Condition 1
为真的情况下进行评估(同样适用于Condition 1
)
答案 3 :(得分:0)
如果您想保证操作顺序,并且性能不是很重要,您可以声明一个表变量来存储前两个条件的结果,然后根据最终条件过滤临时表。例如
declare @tempAnswers table (quesID int, optionid int, answervalue varchar(50))
insert into @tempAnswers
select *
from Answers
where QuesID = 1 and OptionID in (2,5)
select * from @tempAnswers
where convert(float, isnull(AnswerValue, 0)) < 300
答案 4 :(得分:0)
如果升级到SQL Server 2012,则可以使用TRY_CONVERT。它是专有的,但确实解决了这个问题。
SELECT * FROM Answers
WHERE QuesID = 1
AND TRY_CONVERT(int,OptionID) IN (2,5)
AND CONVERT(float, ISNULL(AnswerValue, 0)) < 300