更快的左连接与最后非空

时间:2015-11-24 13:56:24

标签: tsql sql-server-2014

表1:

  • 商店
  • 管理器
  • 日期

表2:

  • 商店
  • 日期
  • 销售

我需要从Table1获取带有Manager字段的Table2。我做了以下技巧:

select
t1.[Shop]
,t1.[Date]
,t1.[Sum]
,t2.[Manager]
from t1 
left join t2
on t1.[Shop] = t2.[Shop] 
and t2.[Date] = (select max(t2.[Date]) from t2 
                 where t2.[Shop] = t1.[Shop] 
                 and t2.[Date] < t1.[Date])

它有效,但是subquerying非常慢,所以我想知道是否有更优雅和快速的方法呢?

要播放的一些示例数据:http://pastebin.com/uLN6x5JE

2 个答案:

答案 0 :(得分:0)

如果您还没有覆盖索引,则可以通过在t2上添加覆盖索引来获得更好的性能:

create index T2ShopDate on t2 ([Shop], [Date]) include ([Manager])

这是一个使用CTE首先查找所有最大经理日期然后再加入t2以获取经理的版本:

;with MaxDates ([Shop], [Date], [Sum], [MaxMgrDate]) as
(
    select
        t1.[Shop]
        ,t1.[Date]
        ,t1.[Sum]
        ,max(t2.[Date])
    from t1
    left join t2
        on t2.[Shop] = t1.[Shop]
        and t2.[Date] < t1.[Date]
    group by
        t1.[Shop]
        ,t1.[Date]
        ,t1.[Sum]
)
select
    MaxDates.[Shop]
    ,MaxDates.[Date]
    ,MaxDates.[Sum]
    ,t2.[Manager]
from MaxDates
inner join t2
   on t2.[Date] = MaxDates.[MaxMgrDate]

您可以使用row_number()

将第二个联接删除回t2
;with MaxDates ([Shop], [Date], [Sum], [Manager], [RowNum]) as
(
    select
        t1.[Shop]
        ,t1.[Date]
        ,t1.[Sum]
        ,t2.[Manager]
        ,row_number() over (partition by (t1.[Shop]) order by t2.[Date] desc)
    from t1
    left join t2
        on t2.[Shop] = t1.[Shop]
        and t2.[Date] < t1.[Date]
)
select *
from MaxDates
where RowNum = 1

答案 1 :(得分:0)

可能看起来像一个回合的方式,但加入单一条件通常更快

select t12.[Shop], t12.[Date], t12.[Sum]
     , t12.[Manager]
from
(  select t1.[Shop], t1.[Date], t1.[Sum]
        , t2.[Manager] 
        , row_number() over (partition by t2.[Shop] order by t2.[Date] desc) as rn
     from t1 
     join t2
           on t2.[Shop] = t1.[Shop] 
          and t1.[Date] < t1.[Date]
) as t12 
where t12.rn = 1 
union 
select t1.[Shop], t1.[Date], t1.[Sum]
     , null as [Manager] 
 from t1 
 left join t2
        on t2.[Shop] = t1.[Shop] 
       and t1.[Date] < t1.[Date]
group by t1.[Shop], t1.[Date], t1.[Sum] 
having count(*) = 1