左外连接Sql server

时间:2017-06-16 07:53:49

标签: sql sql-server sql-server-2012

在我的项目中,我需要在同一个表中找到基于旧版和新版的差异任务。

id     |    task   |   latest_Rev
1             A            N
1             B            N
2             C            Y
2             A            Y
2             B            Y

预期结果:

   id       |     task   | latest_Rev   
   2               C           Y

所以我尝试了以下查询

  Select new.* 
  from Rev_tmp nw with (nolock)
  left outer 
  join rev_tmp  old with (nolock)
  on   nw.id -1  = old.id
  and  nw.task = old.task
  and  nw.latest_rev = 'y'
  where old.task is null

当我的表有超过20k的记录时,这个查询需要更多的时间吗? 如何减少时间?

在我的公司中不允许使用子查询

3 个答案:

答案 0 :(得分:5)

使用LAG功能删除自我加入

SELECT *
FROM   (SELECT *,
               CASE WHEN latest_Rev = 'y' THEN Lag(latest_Rev) OVER(partition BY task ORDER BY id) ELSE NULL END AS prev_rev
        FROM   Rev_tmp) a
WHERE  prev_rev IS NULL 

答案 1 :(得分:0)

  1. latest_Rev应该是比特类型(布尔等价物),我更适合表现(详情here
  2. 可以在id,task上添加索引 ,latest_Rev专栏
  3. 您可以尝试此查询(将左外部替换为不存在)

    Select * 
    from Rev_tmp nw
    where nw.latest_rev = 'y' and not exists
    (
    select * from rev_tmp  old
    where nw.id -1  = old.id and  nw.task = old.task
    )
    

答案 2 :(得分:0)

我的回答是

  • 您无法更改索引
  • 您不能使用子查询
  • 所有字段都单独编制索引

如果查看查询,真正减少结果集的唯一值是latest_rev='Y'。如果你要消除这种情况,你肯定会得到一个表扫描。所以我们希望使用索引来评估该条件。不幸的是,一个只是重视“Y”和“N”的字段可能会被忽略,因为它的选择性很差。如果您哄骗SQL Server使用它,那么可能会获得更好的性能。如果latest_rev上的索引被称为idx_latest_rev,请尝试以下操作:

Set transaction isolated level read uncommitted

Select new.* 
from Rev_tmp nw with (index(idx_latest_rev))
left outer 
join rev_tmp  old 
on   nw.id -1  = old.id
and  nw.task = old.task
where old.task is null
and  nw.latest_rev = 'y'