SQL Server INNER JOIN与WHERE

时间:2016-03-09 18:36:54

标签: sql sql-server

以下哪种解决方案更好。

Declare @ID as int = 1234

Select MAX(q2.ID)
FROM (SELECT col1,col2 FROM table Where ID=@ID) q1 
     INNER JOIN table q2 on q1.col1 = q2.col1 and q1.col2=q2.col2
WHERE q2.ID < q1.ID

VS

Declare @col1Val varchar(50)
Declare @col2Val varchar(50)

Select @col1Val=col1, @col2Val=col2 FROM table where ID=@ID

SELECT MAX(ID) FROM table 
WHERE ID < @ID AND col1 = @col1Val and col2 = @col2Val
  • 这两个选项的性能差异是什么?
  • 为什么没有选项1执行计划报告丢失索引?选项2 报告索引缺少col1,col2?
  • 有更好的选择3吗?

1 个答案:

答案 0 :(得分:0)

查询执行计划可能会让您了解哪个执行计划比另一个执行得更好。看来你已经回顾过了,这很棒。

在第二个查询的情况下,我建议尝试在q2表上的ID,col1和col2上创建索引,然后检查执行计划是否特别显示第二个查询的改进。我希望查询的表现同样出色。这个索引是一个涵盖索引,因为你需要的所有

SELECT MAX(ID) FROM table 
WHERE ID < @ID AND col1 = @col1Val and col2 = @col2Val

将从索引本身找到。

我怀疑你的第一个查询是使用col1和col2索引(我相信它是一个复合索引)用于where子句的分组和ID(我相信它是主键)。第二个查询可能正在尝试使用能够满足where子句的最佳索引并仅使用主键(如果是聚簇,它将在执行计划中显示为聚簇索引)。

您可以尝试另一种选择。我没有针对虚拟表测试此查询,因此您可能需要稍微调整一下

select top 1 q2.id
from table q2
where exists (
  select 1
  from table q1
  where q1.id=@id
    and q1.col1 = q2.col1
    and q1.col2 = q2.col2
    and q1.id > q2.id
)
order by q2.id desc

OR

select max(q2.id)
from table q2
where exists (
  select 1
  from table q1
  where q1.id=@id
    and q1.col1 = q2.col1
    and q1.col2 = q2.col2
    and q1.id > q2.id
)

如果它们是不同的表,则在id,col1和col2上的q1和q2上添加索引。

您还可以从第一个查询中删除where子句,然后尝试:

Select MAX(q2.ID)
FROM (SELECT col1,col2 FROM table Where ID=@ID) q1 
INNER JOIN table q2 on 
  q1.col1 = q2.col1 
  and q1.col2=q2.col2
  and q2.ID < q1.ID

试一试。如果您有示例表结构和数据,请随时使用http://sqlfiddle.com创建示例以获得更好的反馈。