在CASE中多次优化SQL,同一行

时间:2016-11-29 13:37:37

标签: sql sql-server sql-optimization

我编写了一个SQL Servre存储过程(SQL Server 2014),它查看某个表中的某个列,如果结果为null,我想从另一列中获取该值。

我最终写了两次这句话:

(Select t_EC 
 from TTCIB 
 where rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) 
   and t_comp = '50') 

检查它是否为空。

第二次实际将值添加到我的结果中,如果它不是null。

有没有办法优化这个?这样系统不需要两次运行此行? (它有两次ltrim函数和两次rtrim函数,所以它会很有用)

SELECT DISTINCT TOP 15 
    (SELECT t_EC 
     FROM TTCIB 
     WHERE rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) 
       AND t_comp = '18') as EC18,
    CASE 
       WHEN (SELECT t_EC FROM TTCIB 
             WHERE rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) 
               AND t_comp = '50') IS NULL
          THEN (SELECT t_EC 
                FROM TTCIB 
                WHERE rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) 
                  AND t_comp = '51')
          ELSE (SELECT t_EC 
                FROM TTCIB 
                WHERE rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) 
                  AND t_comp = '50') 
    END AS EC50,
    RTRIM(t1.t_sern) AS SerialNumber, t1.t_item AS Item, 
    RTRIM(t1.t_desc) AS ItemDesc, t1.t_ofbp AS SoldToBP,    
    RTRIM(t2.t_nama) AS BPName, t1.t_cwte AS Warranty, 
    t1.t_dltm AS DeliveryTime, t_optm AS InstallationTime,   
    t_clst AS Cluster, ISNULL(t3.t_endt,'1970-01-01') AS EndDate,
    t4.t_csig as ItemSignalCode, t5.t_dsca as ItemSignalCodeDesc  
FROM 
    FnGetSerialNos(@SerialNumber, @MasterCompany) t1  
INNER JOIN 
    ttccom100900 t2 ON t1.t_ofbp = t2.t_bpid
LEFT OUTER JOIN 
    ttsctm120900 t3 ON t1.t_term = t3.t_term
LEFT OUTER JOIN 
    ttcibd001900 t4 ON ltrim(t1.t_item) = ltrim(t4.t_item)
LEFT OUTER JOIN 
    ttcmcs018900 t5 ON t4.t_csig = t5.t_csig

2 个答案:

答案 0 :(得分:0)

使用INNER JOIN读取TTCIB中的所有相关值,并使用COALESCE()函数代替CASE WHEN ... END

SELECT DISTINCT TOP 15 
         x.t_18 as EC18
        ,COALESCE(x.t_50, x.t_51) AS EC50
        ,RTRIM(t1.t_sern) AS SerialNumber
        ,t1.t_item AS Item
        ,RTRIM(t1.t_desc) AS ItemDesc
        ,t1.t_ofbp AS SoldToBP
        ,RTRIM(t2.t_nama) AS BPName
        ,t1.t_cwte AS Warranty
        ,t1.t_dltm AS  DeliveryTime
        ,t_optm AS InstallationTime
        ,t_clst AS Cluster
        , ISNULL(t3.t_endt,'1970-01-01') AS EndDate
        ,t4.t_csig as ItemSignalCode
        , t5.t_dsca as ItemSignalCodeDesc  
FROM FnGetSerialNos(@SerialNumber, @MasterCompany) t1
    INNER JOIN (
        SELECT   RTRIM(LTRIM(t_EC)) AS t_EC
                ,MAX(CASE WHEN t_comp = '18' THEN t_EC END) AS t_18
                ,MAX(CASE WHEN t_comp = '50' THEN t_EC END) AS t_50
                ,MAX(CASE WHEN t_comp = '51' THEN t_EC END) AS t_51
        FROM TTCIB
        GROUP BY t_EC
    ) x
        ON RTRIM(LTRIM(t1.t_item)) = x.t_EC
    INNER JOIN ttccom100900 t2  
        ON t1.t_ofbp = t2.t_bpid
    LEFT OUTER JOIN ttsctm120900 t3  
        ON t1.t_term = t3.t_term
    Left Outer JOIN ttcibd001900 t4  
        ON ltrim(t1.t_item) = ltrim(t4.t_item)
    Left Outer JOIN ttcmcs018900 t5  
        ON t4.t_csig = t5.t_csig
;

答案 1 :(得分:0)

更快(适用​​于所有类型的数据库)

coalesce((Select t_EC from TTCIB where rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) and t_comp = '50'),(Select t_EC from TTCIB where rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) and t_comp = '51')) as EC50

最快(仅限sqlserver,使用此方法的oracle非常复杂)

(Select top 1 t_EC from TTCIB where rtrim(ltrim(t_item)) = rtrim(ltrim(t1.t_item)) and t_comp in ('50','51') order by t_comp asc) as EC50