加入前未过滤数据
Posted
技术标签:
【中文标题】加入前未过滤数据【英文标题】:Data not filtering before a join 【发布时间】:2008-12-03 22:54:42 【问题描述】:来自同事的一个我无法弄清楚的谜题......
update btd.dbo.tblpayroll
set empname = ( select b.Legal_Name
from ( SELECT Legal_Name,
Employee_ID
FROM Com.dbo.Workers
WHERE isnumeric(Employee_ID) = 1
) b
where b.Employee_ID = empnum
and b.Legal_name is not NULL
)
where empname is NULL
消息 245,第 16 级,状态 1,第 1 行 将 varchar 值“N0007”转换为数据类型 int 时转换失败。表别名 b 实际上是一个视图。
值“N0007”在 Workers 表中。我不明白为什么它没有从正在加入的结果中过滤出来。
编辑:
事实上,别名确实返回了正确的行 - 所以 isNumeric 正在完成这项工作。
【问题讨论】:
【参考方案1】:我怀疑优化器试图在内部选择之前应用外部选择的 where 子句。大概它认为它能够对 Employee_ID 进行索引查找,从而在这种情况下实现更快的查询。试试:
update btd.dbo.tblpayroll
set empname = ( select Legal_Name
from Com.dbo.Workers
where isnumeric(Employee_ID) = 1
and convert(varchar,Employee_ID)
= convert(varchar,empnum)
and Legal_name is not NULL)
where empname is NULL
将它们全部转换为 varchar 应该会处理好它。我不认为它的效率比你最初想要的要低得多,因为如果先完成非数字,无论如何都会强制进行表扫描。
【讨论】:
我也认为是优化器。其中 b.Employee_ID = CAST(empnum AS VARCHAR) 应该有帮助 我尝试查看解释计划,看看我是否能发现它 - 但我并不精通阅读它们。您的查询在实际查询中运行良好。谢谢。 @Stanislav -- 我不确定每种类型是什么类型,所以我认为将两者都转换为 varchar 是最安全的选择。【参考方案2】:ISNUMERIC()
对于您正在尝试做的事情是出了名的不可靠。你需要an alternative, which I've been asking for here,比如this one。
【讨论】:
【参考方案3】:显而易见的事情是强制比较的顺序,可能是通过从只有数字 Employee_ID 的视图中获取名称,而不是完整的 Workers 表。
【讨论】:
不幸的是,显而易见的答案是我们首先要做的事情 - 并且令人惊讶地具有相同的行为。【参考方案4】:也许 N 被认为是货币符号?您可以尝试将 IsNumeric 替换为
LIKE REPLICATE('[0-9]',/*length of Employee_ID*/)
或者只是
LIKE '[0-9]%'
如果字母不能在中间
【讨论】:
以上是关于加入前未过滤数据的主要内容,如果未能解决你的问题,请参考以下文章