因多表连接效率很低,希望有人能指点小弟优化下,能提高点效率,谢谢大哥们了
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
如果就是一个多表的左连接,拿这个连接的结果集当一个子查询当查找条件。
1.涉及到计算的关联查询,尽量使用left join 方式,这样可以减少相关表的遍历次数。
2.对数据量较大的表做索引。
3.在语句中加入多的检索条件。比如,默认给一个月的数据。
4.以存储过程的方式实现,当然先期可以在程序员写sql语句,便于调试。
以上是我做多表关联中考虑到的问题,希望对你有用。
这个就是存储过程中的sql语句,我只是拿出来查询的一部分,现在连接的方式就是左连接,真想不出什么优化的地方了,可能是我水平比较低吧 新手程序员。希望大哥能给出一点细致的解答。
isnull(t.DeliveryDate,null) 这种语句没有用啊, 直接t.DeliveryDate 不就好了吗
select distinct OrderID,MIN(CreateDate)as CreateDate
from OrderInfo_StatusHistory with(nolock)
where OperationType = 1
group by OrderID
这个换临时表吧,其他的好像都是业务需要的,就语句来说没什么大的优化空间。看看能不能用内连接。在索引上面想办法吧。
关注下。。。。。。。
这个用的是什么数据库,不同的数据库在优化上好像不太一样。
MSSqlServer
@甄宇: 这个数据库我没接触过。等待别人给你答案吧。
优化点主要是SQL语句连接的部分,
1.可以看出连接的主要表是orderinfo表,而最后的where筛选条件也是针对orderinfo的,可以把筛选放到orderinfo连接处,添加一个子查询,不过这样会导致查询小数据量的数据时候,查询会慢一些,不过对于大数据量提成还是很大的。
2。isnull(t.StartDate,null)这样的语句没有必要
3.