给出以下架构:
create table dbo.SomeTable
(
ID int primary key identity(1, 1),
SomeColumn varchar(50)
);
create index IX_SomeColumn on dbo.SomeTable (SomeColumn);
并填充一些数据:
declare @i int = 1000;
while @i > 0 begin
set @i = @i - 1;
insert dbo.SomeTable (SomeColumn)
values (convert(varchar, @i))
end
此查询执行索引搜索:
select ID
from dbo.SomeTable
where SomeColumn = '431'
此查询执行索引扫描时:
select ID
from dbo.SomeTable
where case when SomeColumn = '431' then 1 else 0 end = 1
有没有办法让后者(或类似的东西)执行索引搜索?
我在问,因为我希望能够将case when
放入视图的选择列表并在where
子句中使用它,但它永远不会像原始一样好用如果我不能让SQL Server进行索引搜索,那么就形成了。
答案 0 :(得分:6)
你可以通过使case when SomeColumn = '431' then 1 else 0 end
表达式成为计算列并索引计算列来获得搜索的唯一方法。
然后,您应该发现表达式与允许搜索的计算列匹配(以维持额外索引为代价)。
(如果您遇到自动对等计划出现问题而无法匹配,则会添加冗余1=1
会阻止此操作。SQL Fiddle with plan showing a seek)
答案 1 :(得分:3)
如果查看两个查询的执行计划,搜索谓词就会大不相同。
当你在where子句中没有使用CASE表达式时,搜索谓词只留下列(不必对列值进行任何计算),只需对索引进行搜索以在另一个上找到值<script type="text/javascript">
jQuery('input[name="location"]').click(function(){
var data = {location : jQuery(this).val(), department : $('input[name="department"]:checked').val()};
jQuery.ajax({
url: "/new-fields.php",
type:'POST',
data: data,
dataType: 'text',
success: function(result){
jQuery('#div-custom').html(result).show();
$("#div-custom").find("script").each(function() {
eval($(this).text());
});
}
});
});
</script>
的一面。
另一方面,当你在where子句中使用CASE表达式时,事情会发生很大的变化,现在搜索谓词已经在Where表达式的两边参数化了where子句。简单来说,在 $picker = '<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script>
$(function() {
$( "#datepicker1" ).datepicker({
numberOfMonths: 3,
showButtonPanel: true
});
});
</script>
<script>
$(function() {
$( "#datepicker2" ).datepicker({
numberOfMonths: 3,
showButtonPanel: true
});
});
</script>
<p>Date: <input type="text" id="datepicker1"></p>
<p>Date: <input type="text" id="datepicker2"></p>';
echo $picker;
实际执行之前,SQL服务器不会产生什么值,因此使用可用的索引选项会超出窗口,SQL服务器最终会进行扫描。
故事的道德
避免在where子句中使用CASE表达式。