2013-04-12 39 views
0

我正在使用多個連接進行查詢。 對於一個「加入」表有一對多關聯,我需要在這一個上進行聚合(SUM)。爲每個提取的記錄計算其他表上的聚合 - 性能

我在每個查詢執行時獲得了大約500到1000條記錄。大約需要100到200毫秒(它有很多連接)。但是在添加聚合之後,它將執行時間增加到大約5-6秒!

我試過2個解決方案(問題是與最後兩米欄:SubchargesToSubchargesFrom),無論是在性能惡化的一大因素:

第一:

SELECT 
      RR.Id, 
      Customer.Name AS Customer, 
      PrincipalsCustomer.Name AS PrincipalsCustomer, 
      EffectiveCarrier.Name AS EffectiveCarrier, 
      CAST(CASE RR.isImport WHEN 1 THEN RR.unloadingDateStart ELSE TR.loadingDateStart END AS DATE) AS LoadingUnloadingDate, 
      RR.containerNo AS ContainerNumber, 
      CASE RR.isImport WHEN 1 THEN PLACEUNLOADING.Name ELSE PlaceLoading.Name END AS LoadingUnloadingPlace, 
      Pol.Name AS POL, 
      Pod.Name AS POD, 
      Commodity.Name AS Commodity, 
      RR.Km AS Km, 
      RR.pricePerKm AS SalesPricePerKM, 
      RR.salesPrice AS SalesPrice, 
      RR.purchasePrice AS PurchasePrice 
      (SELECT SUM(salesAmount*salesCost) FROM TruckingTobaccoSurcharges WHERE TruckingTobaccoSurcharges.REPORT = RR.Id) + 
      (SELECT SUM(incomeAmount*toSBCIncome) FROM TruckingTobaccoSurcharges2 WHERE TruckingTobaccoSurcharges2.REPORT = RR.Id) as SurchargesTo, 
      (SELECT SUM(costAmount*costCost) FROM TruckingTobaccoSurcharges WHERE TruckingTobaccoSurcharges.REPORT = RR.Id) + 
      (SELECT SUM(costAmount*fromCustomerCost) FROM TruckingTobaccoSurcharges2 WHERE TruckingTobaccoSurcharges2.REPORT = RR.Id) as SurchargesFrom 
     FROM Report RR 
      JOIN TruckingReport TR ON TR.REPORT = RR.ID 
      LEFT JOIN Customer ON RR.CUSTOMER = Customer.ID 
      LEFT JOIN PrincipalsCustomer ON RR.PRINCIPALSCUSTOMER = PrincipalsCustomer.ID 
      LEFT JOIN EffectiveCarrier ON RR.EFFECTIVECARRIER = EffectiveCarrier.ID 
      LEFT JOIN PlaceLoading ON TR.PLACELOADING = PlaceLoading.ID 
      LEFT JOIN PlaceUnloading ON RR.PLACEUNLOADING = PlaceUnloading.ID 
      LEFT JOIN Pol ON TR.POL = Pol.Id 
      LEFT JOIN Pod ON TR.POD = Pod.Id 
      LEFT JOIN Commodity ON RR.COMMODITY = Commodity.Id 

的第二個:

SELECT 
      RR.Id, 
      Customer.Name AS Customer, 
      PrincipalsCustomer.Name AS PrincipalsCustomer, 
      EffectiveCarrier.Name AS EffectiveCarrier, 
      CAST(CASE RR.isImport WHEN 1 THEN RR.unloadingDateStart ELSE TR.loadingDateStart END AS DATE) AS LoadingUnloadingDate, 
      RR.containerNo AS ContainerNumber, 
      CASE RR.isImport WHEN 1 THEN PLACEUNLOADING.Name ELSE PlaceLoading.Name END AS LoadingUnloadingPlace, 
      Pol.Name AS POL, 
      Pod.Name AS POD, 
      Commodity.Name AS Commodity, 
      RR.Km AS Km, 
      RR.pricePerKm AS SalesPricePerKM, 
      RR.salesPrice AS SalesPrice, 
      RR.purchasePrice AS PurchasePrice, 
      SUBCH1.sales + SUBCH2.sales AS SurchargesTo, 
      SUBCH1.costs + SUBCH2.costs AS SurchargesFrom 
     FROM Report RR 
      JOIN TruckingReport TR ON TR.REPORT = RR.ID 
      LEFT JOIN Customer ON RR.CUSTOMER = Customer.ID 
      LEFT JOIN PrincipalsCustomer ON RR.PRINCIPALSCUSTOMER = PrincipalsCustomer.ID 
      LEFT JOIN EffectiveCarrier ON RR.EFFECTIVECARRIER = EffectiveCarrier.ID 
      LEFT JOIN PlaceLoading ON TR.PLACELOADING = PlaceLoading.ID 
      LEFT JOIN PlaceUnloading ON RR.PLACEUNLOADING = PlaceUnloading.ID 
      LEFT JOIN Pol ON TR.POL = Pol.Id 
      LEFT JOIN Pod ON TR.POD = Pod.Id 
      LEFT JOIN Commodity ON RR.COMMODITY = Commodity.Id 
      LEFT JOIN (SELECT REPORT, SUM(salesAmount*salesCost) AS sales, SUM(costAmount*costCost) AS costs 
         FROM TruckingTobaccoSurcharges SR1 GROUP BY SR1.REPORT 
         )AS SUBCH1 ON SUBCH1.REPORT = RR.ID 
      LEFT JOIN (SELECT REPORT, SUM(incomeAmount*toSBCIncome) AS sales, SUM(costAmount*fromCustomerCost) AS costs 
         FROM TruckingTobaccoSurcharges2 SR2 GROUP BY SR2.REPORT 
         )AS SUBCH2 ON SUBCH2.REPORT = RR.ID 

有什麼更快的方法來實現所需結果呢? 或者這麼多的連接不能真正讓它更快?

任何幫助表示讚賞=]

編輯:作爲尼古拉Markovinović提示再次快速使它TruckingTobaccoSurcharges表上報告FK

新增指數(使用溶液1)! 雖然沒有嘗試過解決方案2。 仍然我想知道如果我的查詢可能會更好,因爲其他人聲明我不加入,但subquerying ...

+0

第2版,似乎沒什麼問題。兩個表中的報告都有索引嗎? –

+0

嗯。我還沒有在索引中,但在擴展報表上的「索引」後,我有「PK_Report(Clustered)」。 – mbudnik

+1

「報告」欄中的「TruckingTobaccoSurcharges」和「TruckingTobaccoSurcharges2」需要索引。使用[sp_helpidex](http://technet.microsoft.com/en-us/library/ms188771%28v=sql.105%29.aspx)檢查索引。 'sp_helpindex'TruckingTobaccoSurcharges''將顯示此表中的所有索引。如果您在index_keys下沒有看到「報告」作爲起始字段,則需要添加索引:「創建索引ix_TruckingTobaccoSurcharges_Report on TruckingTobaccoSurcharges(報告)」。對於TruckingTobaccoSurcharges2也是如此。如果你需要速度,你必須掌握索引。 –

回答

0

你必須意識到,你沒有加入!
是的,你正在加入,因爲左邊是所有的地方,但實際上不是,這不是你的問題。
你是subquerying檢索你的總和,這是壞的,壞的和壞的。 Subquerying總是慢於加入。

這是一個子查詢,而不是加入:

LEFT JOIN 
( 
    SELECT REPORT, 
      SUM(salesAmount*salesCost) AS sales, 
      SUM(costAmount*costCost) AS costs 
    FROM TruckingTobaccoSurcharges SR1 GROUP BY SR1.REPORT 
) 

因爲你subquerying,在報告索引不使用,所以進展緩慢。

因此,對於你的問題,這裏是應該工作:(要知道,真正的加入!)

SELECT 
    SUM(s.salesAmount * s.salesCost) + SUM(s2.salesAmount * s2.salesCost) AS SurchargesTo, 
    SUM(s.costAmount * s.costCost) + SUM(s2.costAmount * s2.fromCustomerCost) AS SurchargesFrom 
FROM Report RR 
    LEFT JOIN TruckingTobaccoSurcharges s 
     ON s.REPORT = RR.ID 
    LEFT JOIN TruckingTobaccoSurcharges2 ss 
     ON s.REPORT = RR.ID 
GROUP BY s.REPORT 
+0

謝謝! =],讓我試試這個。 – mbudnik

+0

此版本可能會在「TruckingTobaccoSurcharges」和「TruckingTobaccoSurcharges2」之間生成笛卡爾積,除非其中一個表不包含匹配記錄。總計將關閉。 –

+0

我不能在我的查詢中注入您的解決方案,因爲我無法在一個結果中獲得聚合和表列。我應該分組所有其他列嗎? – mbudnik