多联接Tsql Coalesce低效代码

时间:2018-07-18 16:26:28

标签: sql-server tsql join pivot coalesce

需要帮助提高代码的效率。

我有以下选择(将成为更新语句),现在我必须有8个完全相同的数据联接。我尝试了一些尝试并失败了,但也许这里的集体智慧将对如何提高效率有所帮助。

我有下表

#temp_data 
customer    season  id      percent
1           2016    835     35.93000    
1           2016    836     31.82000    
1           2016    837     11.88000    
1           2016    841     5.09000 
1           2016    839     15.28000    
1           2017    836     31.40000
1           2017    837     11.45000    
1           2017    839     14.04000    
1           2017    841     6.40000 
1           2017    835     36.70000

lt_program_data

customer season     value_835   value_836   value_837   value_838   value_839   value_840   value_841   value_842
1       2016        35.93000    31.82000    11.88000    NULL        15.28000    NULL        5.09000     NULL
1       2017        36.70000    31.40000    11.45000    NULL        14.04000    NULL        6.40000     NULL
1       2018        NULL        NULL        NULL        NULL        NULL        NULL        NULL        NULL
1       2019        NULL        NULL        NULL        NULL        NULL        NULL        NULL        NULL

正在发生的事情是,我们将季节/客户/ id值的两个表进行了匹配。在#temp_data表中不存在任何值的情况下,我们使用存在的最大值。我能够整理代码以使其正常工作。但是,它又大又丑,效率不高。

我要么必须拥有8条更新语句,否则我必须明确声明每个id值(835、836等)。或带有8个Join的一个大型语句几乎是同一件事。关于如何更新以下内容以提高效率的任何建议都很好。

如您所见,以下内容实际上是一遍又一遍地重复完全相同的事情。虽然我知道选择部分可能需要8个单独的语句,但有一种方法可以消除剩下的8个外部联接是唯一的。

代码:

select      a.customer, 
            fyear,
            value_835 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 835),    
                                        c1.[percent] ),

            value_836 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 836),    
                                        c2.[percent] ),

            value_837 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 837),    
                                        c3.[percent] ),

            value_838 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 838),    
                                        c4.[percent] ),

            value_839 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 839),    
                                        c5.[percent] ),

            value_840 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 840),    
                                        c6.[percent] ),

            value_841 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 841),    
                                        c7.[percent] ),

            value_842 = coalesce (( select [percent] from #temp_data d where d.season = a.fyear and d.customer = a.customer and d.id = 842),    
                                        c8.[percent] )
from        #lt_program_data a
left outer join (   --835
                    select a.customer, a.id, a.[percent] 
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 835
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c1 on        a.customer = c1.customer 

left outer join (   --836
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 836
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c2 on        a.customer = c2.customer 

left outer join (   --837
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 837
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c3 on        a.customer = c3.customer 

left outer join (   --838
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 838
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c4 on        a.customer = c4.customer 

left outer join (   --839
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 839
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c5 on        a.customer = c5.customer 

left outer join (   --840
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 840
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c6 on        a.customer = c6.customer 


left outer join (   --841
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 841
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c7 on        a.customer = c7.customer 


left outer join (   --842
                    select a.customer, a.id, a.[percent]
                    from    #temp_data a
                    join    (   select z.customer, id, season =  max(z.season)
                                from    #temp_data z 
                                where   id = 842
                                group by z.customer, id 
                            )   b on a.customer = b.customer and a.season = b.season  and a.id = b.id 
                )  c8 on        a.customer = c8.customer 

这是最后的示例输出。

customer    fyear   value_835   value_836   value_837   value_838   value_839   value_840   value_841   value_842
1           2016    35.93000    31.82000    11.88000    NULL        15.28000    NULL        5.09000     NULL
1           2017    36.70000    31.40000    11.45000    NULL        14.04000    NULL        6.40000     NULL
1           2018    36.70000    31.40000    11.45000    NULL        14.04000    NULL        6.40000     NULL
1           2019    36.70000    31.40000    11.45000    NULL        14.04000    NULL        6.40000     NULL

1 个答案:

答案 0 :(得分:0)

我发现将逻辑查询块包装在CTE中可以帮助我更清楚地考虑它。这是pivots #temp_data而不是unpivot的lt_program_data之一。 如果我对您的理解正确,那么您应该能够使用最新数据 left outer join cross apply来获取所需的信息。

;with LatestData as (
    select Customer, Season, [835],[836],[837],[838],[839],[840],[841],[842] from 
    (select Customer, Season, [percent], id from temp_data td) as TempSource
    pivot 
    ( sum([percent]) for id in ([835],[836],[837],[838],[839],[840],[841],[842])) as TempPivoted
    )

 select a.customer,
    a.season,
    value_835 = coalesce(a.value_835, latest.[835]),
    value_836 = coalesce(a.value_836, latest.[836]),
    value_837 = coalesce(a.value_837, latest.[837]),
    value_838 = coalesce(a.value_838, latest.[838]),
    value_839 = coalesce(a.value_839, latest.[839]),
    value_840 = coalesce(a.value_840, latest.[840]),
    value_841 = coalesce(a.value_841, latest.[841]),
    value_842 = coalesce(a.value_842, latest.[842])
from lt_program_data a
cross apply (select top 1 * from LatestData where LatestData.customer = a.customer and latestdata.season <= a.season order by season desc) as latest