首页 新闻 会员 周边

多表连接sql语句的优化

0
悬赏园豆:30 [已解决问题] 解决于 2013-05-09 09:21

因多表连接效率很低,希望有人能指点小弟优化下,能提高点效率,谢谢大哥们了

 

SELECT
        t.OrderChannel,t.OrderID,t.state,t.Name,t.city,t.city2,t.city3,t.cityName,t.city2Name,t.city3Name,t.BigRegion,t.CityLevel,
        t.AddDate,--下单时间
        t.CreateDate,---下载时间
        t.CreateDate2, --打印时间
        t.StartDate ,--拣货开始时间
        t.EndDate, --拣货结束时间
        t.CreateDate3,---第一次分拣时间
        t.SortingDate2,---最后一次分拣时间
        t.SortingDate,---分拣成功时间
        t.AuditDate,---出库审核时间
        t.AuditDate2,---发货审核时间
        t.DeliveryDate,---送达时间
        t.DeliveryState,t.ExpressCorpID,t.ExpressCorp,t.SendBill_Code,
        round(convert([float],DATEDIFF(Minute,isnull(t.AddDate,null),isnull(t.SortingDate2,null)))/60,1)SortingHour,--C2A(下单-分拣)
        round(convert([float],DATEDIFF(Minute,isnull(t.SortingDate2,null),isnull(t.AuditDate,null)))/60,1)OuterHour,--A2P(分拣-出库)
        round(convert([float],DATEDIFF(Minute,isnull(t.AuditDate,null),isnull(t.AuditDate2,null)))/60,1) OutboundDelivery,--P2S(出库-发货)
        round(convert([float],DATEDIFF(Minute,isnull(t.AuditDate2,null),isnull(t.DeliveryDate,null)))/60,1)DeliveryReceiving,--S2D(发货-送达)
        round(convert([float],DATEDIFF(Minute,isnull(t.StartDate,null),isnull(t.EndDate,null)))/60,1)PickGoodOver, ---拣货开始到结束
        round(convert([float],DATEDIFF(Minute,isnull(t.AddDate,null),isnull(t.DeliveryDate,null)))/60,1)SendBillHour, --C2D(下单-收)
        t.Creator,t.User_TrueName,t.Auditor,Auditor2
    FROM    
    (
        SELECT   
            MAX(O.OrderChannel)OrderChannel,----订单渠道  
            O.OrderID ,  
            MAX(O.state) state,---订单状态  
            MAX(O.Name) Name,----收件人  
            MAX(O.city) city,MAX(O.city2) city2,MAX(O.city3)city3,  
            MAX(O.cityName) cityName,MAX(O.city2Name) city2Name,MAX(O.city3Name) city3Name,  
            MAX(O.AddDate)AddDate,---下单时间  
            (CASE WHEN MAX(O.CreateDate)  = '1900-01-01 00:00:00.000' then null ELSE MAX(O.CreateDate) END)CreateDate,---下载时间  
            (CASE WHEN MAX(OP.CreateDate)  = '1900-01-01 00:00:00.000' then null ELSE MAX(OP.CreateDate) END)CreateDate2, --打印时间  
            (CASE WHEN MAX(OA.StartDate) = '1900-01-01 00:00:00.000' THEN null ELSE MAX(OA.StartDate)END)StartDate ,--拣货开始时间  
            (CASE WHEN MAX(OA.EndDate)  = '1900-01-01 00:00:00.000' THEN null ELSE MAX(OA.EndDate) END)EndDate, --拣货结束时间  
            MIN(tt.CreateDate)AS CreateDate3,---第一次分拣时间  
            (CASE WHEN MAX(O.SortingDate) ='1900-01-01 00:00:00.000' THEN null ELSE MAX(O.SortingDate)END)SortingDate2,---最后一次分拣时间
            (CASE WHEN ((MAX(SortingStatus)<>2) OR (MAX(O.SortingDate) = '1900-01-01 00:00:00.000')) THEN null ELSE MAX(O.SortingDate)END)SortingDate,---分拣成功时间

            (CASE WHEN MAX(S.AuditDate) = '1900-01-01 00:00:00.000' THEN null ELSE MAX(S.AuditDate)END)AuditDate,---出库审核时间  
            (CASE WHEN MAX(ss.AuditDate) = '1900-01-01 00:00:00.000' THEN null ELSE MAX(ss.AuditDate)END)AuditDate2,---发货审核时间  
            (CASE WHEN MAX(O.DeliveryDate) = '1900-01-01 00:00:00.000' THEN null ELSE MAX(O.DeliveryDate)END)DeliveryDate,---送达时间  
            MAX(O.DeliveryState) DeliveryState,---配送状态  
            MAX(ss.ExpressCorpID) as ExpressCorpID,---配送公司ID  
            MAX(ss.ExpressCorp)ExpressCorp,---配送公司  
            MAX(ss.SendBill_Code) SendBill_Code,---发货单号   
            MAX(SU.User_Name) Creator, ---打印人  
            MAX(OA.User_TrueName)User_TrueName, ---拣货人  
            MAX(S.Auditor) Auditor, ---出库人  
            MAX(ss.Auditor) Auditor2, ---发货人  
            BigRegion,CityLevel
        FROM Orderinfo O  with(nolock)  
        LEFT JOIN  
            Sale_SendBillList st with(nolock)  
        ON st.OrderID = o.OrderID   
        LEFT JOIN  
            Sale_SendBill ss with(nolock)  
        ON st.SendBill_Id = ss.SendBill_Id  
        LEFT JOIN  
            Sale_Outer S with(nolock)  
        ON O.OrderID = s.OrderID  
        LEFT JOIN  
            OrderInfo_Allot OA with(nolock)  
        ON O.PrintBatch_Code = OA.PrintBatch_Code  
        LEFT JOIN  
            OrderInfo_PrintBatch OP with(nolock)  
        ON O.PrintBatch_Code = OP.PrintBatch_Code  
        LEFT JOIN  
            Sys_User SU with(nolock)  
        on SU.User_Name = OP.Creator
        LEFT JOIN  
        (  
            select distinct OrderID,MIN(CreateDate)as CreateDate   
            from OrderInfo_StatusHistory with(nolock)  
            where OperationType = 1  
            group by OrderID  
        )tt  
        ON O.OrderID = tt.OrderID
        LEFT JOIN
        Base_City BC with(nolock)
        on S.Cityid=BC.CityId
            
        where O.AddDate IS NOT NULL   
        AND O.AddDate <> '1900-01-01 00:00:00.000'  
        GROUP BY O.OrderID ,O.typeid,BigRegion,CityLevel
    ) t

问题补充:

如果就是一个多表的左连接,拿这个连接的结果集当一个子查询当查找条件。

甄宇的主页 甄宇 | 初学一级 | 园豆:2
提问于:2013-05-06 09:15
< >
分享
最佳答案
0

1.涉及到计算的关联查询,尽量使用left join 方式,这样可以减少相关表的遍历次数。

2.对数据量较大的表做索引。

3.在语句中加入多的检索条件。比如,默认给一个月的数据。

4.以存储过程的方式实现,当然先期可以在程序员写sql语句,便于调试。

以上是我做多表关联中考虑到的问题,希望对你有用。

收获园豆:20
jerry-Tom | 老鸟四级 |园豆:4077 | 2013-05-06 09:47

这个就是存储过程中的sql语句,我只是拿出来查询的一部分,现在连接的方式就是左连接,真想不出什么优化的地方了,可能是我水平比较低吧 新手程序员。希望大哥能给出一点细致的解答。

甄宇 | 园豆:2 (初学一级) | 2013-05-06 10:23
其他回答(5)
0

isnull(t.DeliveryDate,null)  这种语句没有用啊, 直接t.DeliveryDate 不就好了吗

收获园豆:10
gunsmoke | 园豆:3592 (老鸟四级) | 2013-05-06 10:16
1

  select distinct OrderID,MIN(CreateDate)as CreateDate   
            from OrderInfo_StatusHistory with(nolock)  
            where OperationType = 1  
            group by OrderID 

这个换临时表吧,其他的好像都是业务需要的,就语句来说没什么大的优化空间。看看能不能用内连接。在索引上面想办法吧。

清海扬波 | 园豆:825 (小虾三级) | 2013-05-06 11:18
0

关注下。。。。。。。

@@@一统@@@ | 园豆:1551 (小虾三级) | 2013-05-06 12:35
0

这个用的是什么数据库,不同的数据库在优化上好像不太一样。

Wolfe Yu | 园豆:434 (菜鸟二级) | 2013-05-06 14:35

MSSqlServer

支持(0) 反对(0) 甄宇 | 园豆:2 (初学一级) | 2013-05-06 18:56

@甄宇: 这个数据库我没接触过。等待别人给你答案吧。

支持(1) 反对(0) Wolfe Yu | 园豆:434 (菜鸟二级) | 2013-05-07 09:22
0

优化点主要是SQL语句连接的部分,

1.可以看出连接的主要表是orderinfo表,而最后的where筛选条件也是针对orderinfo的,可以把筛选放到orderinfo连接处,添加一个子查询,不过这样会导致查询小数据量的数据时候,查询会慢一些,不过对于大数据量提成还是很大的。

2。isnull(t.StartDate,null)这样的语句没有必要

3.

甄宇 | 园豆:2 (初学一级) | 2013-05-09 09:20
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册