2016-03-05 94 views
1

這是我的查詢。此查詢導致20-30秒,並在我的應用程序中導致超時錯誤。我試圖用條款重新寫,但我不能讓它運行。如何快速從子表中選擇2000萬行數據的子查詢

對不起,我英文很差。

SELECT 
    StationName, StationID, 
    (SELECT TOP (1) ISNULL(SUM(Liter), 0) AS TotalLiter 
    FROM Transactions (nolock) 
    WHERE (StationID = s.StationID) 
     AND (SaleDate>= CONVERT(date, GETDATE())) 
     AND (FuelTypeID = 1)) AS Total1, 
    (SELECT TOP (1) ISNULL(SUM(Liter), 0) AS TotalLiter 
    FROM dbo.Transactions (nolock) AS Transactions_11 
    WHERE (StationID = s.StationID) 
     AND (SaleDate >= CONVERT(date, GETDATE())) 
     AND (FuelTypeID = 2)) AS Total2, 
    (SELECT TOP (1) ISNULL(SUM(Liter), 0) AS TotalLiter 
    FROM dbo.Transactions (nolock) AS Transactions_10 
    WHERE (StationID = s.StationID) 
     AND (SaleDate >= CONVERT(date, GETDATE())) 
     AND (FuelTypeID = 3)) AS Total3, 
    (SELECT TOP (1) ISNULL(SUM(Liter), 0) AS TotalLiter 
    FROM dbo.Transactions (nolock) AS Transactions_9 
    WHERE (StationID = s.StationID) 
     AND (SaleDate >= CONVERT(date, GETDATE())) 
     AND (FuelTypeID = 4)) AS Total4, 
    (SELECT TOP (1) ISNULL(SUM(Liter), 0) AS TotalLiter 
    FROM dbo.Transactions (nolock) AS Transactions_8 
    WHERE (StationID = s.StationID) 
     AND (SaleDate >= CONVERT(date, GETDATE())) 
     AND (FuelTypeID = 5)) AS Total5, 
        (SELECT TOP (1) ISNULL(SUM(Liter),0) AS TotalLiter 
        FROM  dbo.Transactions (nolock) AS Transactions_7 
        WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE())) AND (FuelTypeID = 6)) AS Total6, 
        (SELECT TOP (1) ISNULL(SUM(Liter),0) AS TotalLiter 
        FROM  dbo.Transactions (nolock) AS Transactions_6 
        WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE())) AND (FuelTypeID = 7)) AS Total7, 
        (SELECT TOP (1) ISNULL(SUM(Liter),0) AS TotalLiter 
        FROM  dbo.Transactions (nolock) AS Transactions_5 
        WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE())) AND (FuelTypeID = 8)) AS Total8, 
        (SELECT TOP (1) ISNULL(SUM(Liter),0) AS TotalLiter 
        FROM  dbo.Transactions (nolock) AS Transactions_4 
        WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE())) AND (FuelTypeID = 9)) AS Total9, 
        (SELECT TOP (1) ISNULL(SUM(Liter),0) AS TotalLiter 
        FROM  dbo.Transactions (nolock) AS Transactions_3 
        WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE())) AND (FuelTypeID = 10)) AS Total10, 
        (SELECT TOP (1) ISNULL(SUM(Liter),0) AS TotalLiter 
        FROM  dbo.Transactions (nolock) AS Transactions_2 
        WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE()))) AS GrandTotal, 
        (SELECT TOP (1) MAX(SaleDate) AS LastSaleDate 
        FROM  dbo.Transactions (nolock) AS Transactions_1 
WHERE (StationID = s.StationID) AND (SaleDate >= CONVERT(date, GETDATE())) 
        ORDER BY LastSaleDate) AS LastSaleDate 
FROM  
    dbo.Stations (nolock) AS s 
WHERE 
    s.StationCode BETWEEN 1000 AND 1100 
ORDER BY 
    StationID 
+0

添加表結構,樣本da ta和預期結果 – Backs

回答

4

您可以使用Outer ApplyConditional Aggregate避免運行相同Sub-Query多次

嘗試是這樣的

SELECT StationName, 
     StationID, 
     Total1, 
     Total2, 
     Total3, 
     Total4 
     ... 
     GrandTotal, 
     LastSaleDate 
FROM dbo.Stations (nolock) AS s 
     OUTER apply (SELECT Sum(CASE WHEN t.FuelTypeID = 1 THEN Liter END) AS Total1, 
          Sum(CASE WHEN t.FuelTypeID = 2 THEN Liter END) AS Total2, 
          Sum(CASE WHEN t.FuelTypeID = 3 THEN Liter END) AS Total3, 
          Sum(CASE WHEN t.FuelTypeID = 4 THEN Liter END) AS Total4, 
          ... 
          Sum(Liter) as GrandTotal, 
          Max(SaleDate) AS LastSaleDate 
        FROM Transactions t 
        WHERE t.StationID = s.StationID 
          AND t.SaleDate >= CONVERT(DATE, Getdate())) ou 
WHERE s.StationCode BETWEEN 1000 AND 1100 
ORDER BY StationID 

也不要忘了閱讀這篇文章:Bad habits : Putting NOLOCK everywhere

+0

我知道nolock的壞影響,但我把它作爲最後的手段。並感謝您的回覆。你的方式比我的問題更好,更乾淨:) –

0
SELECT s.StationName, s.StationID, 
      sum(Total6.ttl) as [Total6.ttl], 
      sum(Total7.ttl) as [Total7.ttl], 
      sum(Total8.ttl) as [Total8.ttl], 
      sum(Total9.ttl) as [Total9.ttl], 
      sum(TotalG.ttl) as [TotalG.ttl], 
      max(TotalG.LastSaleDate) as [LastSaleDate.ttl], 
     FROM dbo.Stations (nolock) AS s 
LEFT JOIN Transactions Total6 
      on Total6.StationID = s.StationID 
      and Total6.FuelTypeID = 6 
      and Total6.SaleDate >= CONVERT(DATE, Getdate()) 
LEFT JOIN Transactions Total7 
      on Total7.StationID = s.StationID 
      and Total7.FuelTypeID = 7 
      and Total7.SaleDate >= CONVERT(DATE, Getdate()) 
LEFT JOIN Transactions Total8 
      on Total8.StationID = s.StationID 
      and Total8.FuelTypeID = 8 
      and Total8.SaleDate >= CONVERT(DATE, Getdate()) 
LEFT JOIN Transactions Total9 
      on Total9.StationID = s.StationID 
      and Total9.FuelTypeID = 9 
      and Total9.SaleDate >= CONVERT(DATE, Getdate()) 
LEFT JOIN Transactions TotalG 
      on TotalG.StationID = s.StationID 
      and TotalG.SaleDate >= CONVERT(DATE, Getdate()) 
    WHERE s.StationCode BETWEEN 1000 AND 1100 
    GROUP BY s.StationName, s.StationID