如何强制SQL Server 2005在哪里之前运行连接?
-
10-07-2019 - |
题
我有一个SQL查询,它将定价表连接到包含用户提供的答案的表。我的查询用于根据输入的数量获取价格。下面是我的SQL语句:
SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK
AND JobQuestion.JobFK=1
WHERE Price.Min <= JobQuestion.Value
AND Price.Max >= JobQuestion.Value
问题是SQL Server在JOIN之前运行where子句并且它抛出了错误:
转换时转换失败 varchar值'TEST'到数据类型int。
因为它在连接之前进行最小和最大比较('TEST'是JobQuestion表中有效的用户输入值,但是当JobQuestion加到Price时不应该返回)。我相信SQL Server正在选择运行WHERE,因为出于某种原因,解析器认为这将是一个更有效的查询。如果我只是运行
SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK
AND JobQuestion.JobFK=1
我得到了这些结果:
500 1 500 272.00
500 501 1000 442.00
500 1001 2000 782.00
因此,添加WHERE应该过滤掉最后两个并返回第一条记录。如何强制SQL首先运行JOIN或使用其他技术过滤掉我需要的记录?
解决方案
首先,这很可能是设计不佳的迹象 如果您无法更改架构,那么您可以使用提示。引用:
提示是指定用于SQL Server查询处理器对SELECT,INSERT,UPDATE或DELETE语句强制执行的选项或策略。提示会覆盖查询优化器可能为查询选择的任何执行计划。
还有一些:
<强>注意:强>结果 由于SQL Server查询优化器通常会为查询选择最佳执行计划,因此我们建议<!> lt; join_hint <!> gt;,<!> lt; query_hint <!> gt;和<!> lt; table_hint GT <!>;仅供有经验的开发人员和数据库管理员使用。
其他提示
尝试<!>“重新措辞<!>”;查询如下:
SELECT *
FROM (
SELECT JobQuestion.Value,
Price.Min,
Price.Max,
Price.Amount
FROM Price
INNER
JOIN JobQuestion
ON Price.QuestionFK = JobQuestion.QuestionFK
AND JobQuestion.JobFK = 1
) SQ
WHERE SQ.Min <= SQ.Value
AND SQ.Max >= SQ.Value
根据Christian Hayter的回答,如果您有选择,请更改表格设计=)
您不应该将字符串与int进行比较。如果您对表格设计有任何影响,则将JobQuestion.Value
列的两种不同用法分成两个不同的列。
如果您对表格设计没有影响 - 您是否可以尝试使用 ISNUMERIC ()?我想将这个添加到你的where子句可以帮助。
你可以删除where ...并将它们作为谓词添加到你的连接中。因为它是一个内连接,所以应该可以工作
SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount
FROM Price
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK
AND JobQuestion.JobFK=1
AND Price.Min <= JobQuestion.Value
AND Price.Max >= JobQuestion.Value
您可以在该字符串列上使用TRY_PARSE转换为数字,如果SQL无法转换,则会获得NULL而不是错误消息。
P.S。这是第一次在SQL 2012中引入,所以可能会有所帮助。