create table dbo.Parent (
Id bigint NOT NULL,
TypeId int NOT NULL
)
create table dbo.Child (
Id bigint NOT NULL,
ParentId bigint NOT NULL,
TypeId int NOT NULL,
varcharColumn varchar(300) NULL
)
select cast(c.varcharColumn as int)
from dbo.Parent p (nolock)
inner join dbo.Child c (nolock)
on p.Id = c.ParentId
and c.TypeId = 2
where p.TypeId = 13
由于无法将其转换为int的值,因此发生了强制转换。在这种情况下:“ 123-1”。奇怪的是,要转换的值会从最终结果集中过滤掉。
select c.varcharColumn
from dbo.Parent p (nolock)
inner join dbo.Child c (nolock)
on p.Id = c.ParentId
and c.TypeId = 2
where p.TypeId = 13
and c.varcharColumn = '123-1'
查询计划最终查看了子表,并在where子句之前实际应用了强制转换功能。
我们能够通过在子表上创建新索引来解决此问题(它正在执行PK 扫描 )
create index [NCIDX_dbo_Child__TypeId] on dbo.Child (
TypeId
)
include (
ParentId,
varcharColumn
)
现在,它首先过滤父表的where子句。
没有额外的索引,有什么方法可以解决此问题?同样,请避免提出任何与修复我们的架构有关的建议。在这种情况下,这绝对是正确的解决方法。
我最想了解的是为什么它在过滤结果集之前应用了强制类型转换。
谢谢
非常感谢亚伦和戈登。如果我获得超过15个代表点,我会回头再谈您的两个回答。
我们最终需要Gordon的答案,因为我们想在视图中使用此查询。办公室中的一些人对使用案例声明感到谨慎,因为他们希望对确保我们首先拥有较小的结果集(Aaron的答案)有更多的控制权,但是这全都归结为查看查询计划并检查您的阅读结果计数。
再次感谢您的所有答复!
首先,这不是一个“明显的设计问题”。SQL是输出的描述性语言,而不是指定如何进行练习的过程性语言。通常,不能保证处理顺序,这是一个优势。我可能会说存在一个设计问题,但这是有关SQL语句中异常的一般处理。
根据SQL Server文档(http://msdn.microsoft.com/zh-cn/library/ms181765.aspx),
对于标量表达式 ,您可以依赖CASE语句的评估顺序。因此,以下应该工作:
select (case when isnumeric(c.varcharColumn) = 1 then cast(c.varcharColumn as int) end)
或者,更接近“ int”表达式:
select (case when isnumeric(c.varcharColumn) = 1 and c.varcharColumn not like '%.%' and c.varcharColumn not like '%e%'
then cast(c.varcharColumn as int)
end)
至少您的代码正在执行显式的CAST。当强制转换是隐式的(并且有数百列)时,这种情况更加糟糕。
问题内容: 在我的表中,我有一个可为空的bit列(旧系统…),另一位开发人员最近对存储过程进行了更改,以仅显示bit列不为真的值(1)。因为这是一个可为空的列,所以我们注意到,如果该列为NULL,则不会选择该记录。为什么是这样? 我和其他开发人员都同意NULL <> 1 …这是SQL中的错误还是设计这种方式?似乎是设计缺陷。 当前代码: 建议的修复: (Jon Erickson) VoidedIn
为什么可以在where子句中包含而只保留字母? 编辑1这里是解释:
问题内容: 在WHERE子句中有使用SELECT语句描述的名称吗?这是好/不好的做法吗? 这会是更好的选择吗? 它远没有那么优雅,但是运行起来比以前的版本要快。我不喜欢它,因为它在GUI中没有非常清晰地显示(并且SQL初学者需要理解它)。我可以将其分为两个独立的查询,但是随后事情变得混乱了…… 注意:我不仅需要日期和分数(例如姓名) 问题答案: 称为相关子查询。它有它的用途。
问题内容: 我将如何在没有硬编码值的情况下编写此sql语句? 宁愿有这样的事情: 提前致谢.. 问题答案: 用您当前的方式构造SQL查询是一个糟糕的主意,因为它为各种SQL注入攻击打开了大门 。为了正确执行此操作,您必须改为使用“ 预备语句”。这也将解决您目前显然遇到的各种逃避问题。 请注意,这是一个昂贵的调用(除非您的应用程序服务器使用语句缓存和其他类似的功能)。从理论上讲,最好先准备一次语句,
我正在为一个SQL的实现工作,它应该在Where和Having子句之间使用联合操作来显示结果。例如, sql语句的目的是返回同时满足where和having条件的结果集。 resultset1<=select*from table1,其中col1='get';resultset2<=select*from table1 group by col2 avg(col3)>30 final result
问题内容: 我正在尝试比较两个表以在每个表中找到不在另一个表中的行。表1的groupby列用于在表1中创建2组数据。 表2只有一栏。 因此,表1在组2中具有值1,2,4,表2具有值1,3,4。 加入第2组时,我期望得到以下结果: 我可以使它起作用的唯一方法是在第一个联接中放置where子句: 第二个在“打开”中有一个过滤器: 谁能提出一种不在on子句中而是在where子句中使用过滤器的方法? 上下