简体   繁体   中英

SQL Server : query optimization in stored procedure

Please let me know how can optimize this SQL Server query:

SELECT 
    C.Id AS CurrencyId, C.DisplayName AS CurrencyName, 
    C.TickerSymbol AS TickerSymbol, 
    m.DisplayName AS MarketName, C.BaseCurrency AS BaseCurrency, 
    C.BaseCurrencySymbol AS CurrencySymbol, C.IsActiveImport AS ActiveImport,
    (SELECT TOP 1 Price 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS Price,
    (SELECT TOP 1 Open_24h 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS Open24H,
    (SELECT TOP 1 Volume_24h 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS Volume24H,
    (SELECT TOP 1 Low_24h 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS Low24H,
    (SELECT TOP 1 High_24h 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS High24H,
    (SELECT TOP 1 BestBid 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS BestBid,
    (SELECT TOP 1 BestAsk 
     FROM CurrencyRates 
     WHERE C.Id = ProductId 
     ORDER BY PriceDate DESC) AS BestAsk
FROM 
    Currencies C
INNER JOIN 
    CryptoMarketsMaster M ON C.CryptoMarketId = C.CryptoMarketId

You can make use of analytical functions for first_value to get all of the data from CurrencyRates table and join it once instead of a select in a select query.

This would be useful if you are batch processing the data(ie you wish to optimize the select output for all the rows to be returned)

If you are building a app/ui screen with pagination then select in a select would be more suitable as it would be optimized for getting the first_rows first.

SELECT C.Id AS CurrencyId
          , C.DisplayName AS CurrencyName
          , C.TickerSymbol AS TickerSymbol
          , m.DisplayName AS MarketName
          , C.BaseCurrency AS BaseCurrency
          , C.BaseCurrencySymbol AS CurrencySymbol
          , C.IsActiveImport AS ActiveImport
          /*
          , (SELECT TOP 1 Price FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC)      AS Price
          , (SELECT TOP 1 Open_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC)   AS Open24H
          , (SELECT TOP 1 Volume_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Volume24H
          , (SELECT TOP 1 Low_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC)    AS Low24H
          , (SELECT TOP 1 High_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC)   AS High24H
          , (SELECT TOP 1 BestBid FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC)    AS BestBid
          , (SELECT TOP 1 BestAsk FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC)    AS BestAsk
          */
          , Cr.Price
          , Cr.Open24H
          , Cr.Volume24H
          , Cr.Low24H
          , Cr.High24H
          , Cr.BestBid
          , Cr.BestAsk
          FROM Currencies C
    INNER JOIN CryptoMarketsMaster M 
            ON C.CryptoMarketId = C.CryptoMarketId
          JOIN (SELECT  /*first_value(Price) over(partition by productId order by price_date desc) as price
                       ,first_value(Open_24h) over(partition by productId order by price_date desc) as Open_24h
                       ,first_value(Volume_24h) over(partition by productId order by price_date desc) as Volume_24h
                       ,first_value(Low_24h) over(partition by productId order by price_date desc) as Low_24h
                       ,first_value(High_24h) over(partition by productId order by price_date desc) as High_24h
                       ,first_value(BestBid) over(partition by productId order by price_date desc) as BestBid
                       ,first_value(BestAsk) over(partition by productId order by price_date desc) as BestAsk
                       */
                       , Price
                       , Open24H
                       , Volume24H
                       , Low24H
                       , High24H
                       , BestBid
                       , BestAsk
                       ,row_number() over(partition by productId order by price_date desc) as rnk
                       ,productId
                  FROM CurrencyRates      
                )Cr
             ON C.Id=Cr.productId   
            AND Cr.rnk=1

Hi Shailesh Kalasariya,

You could outer apply to combine these top subqueries into one subquery like this.

SELECT 
C.Id AS CurrencyId, 
C.DisplayName AS CurrencyName, 
C.TickerSymbol AS TickerSymbol, 
m.DisplayName AS MarketName, 
C.BaseCurrency AS BaseCurrency, 
C.BaseCurrencySymbol AS CurrencySymbol, 
C.IsActiveImport AS ActiveImport,
/*
(SELECT TOP 1 Price FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Price,
(SELECT TOP 1 Open_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Open24H,
(SELECT TOP 1 Volume_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Volume24H,
(SELECT TOP 1 Low_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Low24H,
(SELECT TOP 1 High_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS High24H,
(SELECT TOP 1 BestBid FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS BestBid,
(SELECT TOP 1 BestAsk FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS BestAsk
*/
D.Price,
D.Open_24h,
D.Volume_24h,
D.Low_24h,
D.High_24h,
D.BestBid,
D.BestAsk
FROM Currencies C
INNER JOIN CryptoMarketsMaster M ON C.CryptoMarketId = C.CryptoMarketId
OUTER APPLY (SELECT TOP 1 Price,Open_24h,Volume_24h,Low_24h,High_24h,BestBid,BestAsk FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) D

Or you could use row_number function to rewrite this.

SELECT 
C.Id AS CurrencyId, 
C.DisplayName AS CurrencyName, 
C.TickerSymbol AS TickerSymbol, 
m.DisplayName AS MarketName, 
C.BaseCurrency AS BaseCurrency, 
C.BaseCurrencySymbol AS CurrencySymbol, 
C.IsActiveImport AS ActiveImport,
/*
(SELECT TOP 1 Price FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Price,
(SELECT TOP 1 Open_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Open24H,
(SELECT TOP 1 Volume_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Volume24H,
(SELECT TOP 1 Low_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS Low24H,
(SELECT TOP 1 High_24h FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS High24H,
(SELECT TOP 1 BestBid FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS BestBid,
(SELECT TOP 1 BestAsk FROM CurrencyRates WHERE C.Id=ProductId ORDER BY PriceDate DESC) AS BestAsk
*/
D.Price,
D.Open_24h,
D.Volume_24h,
D.Low_24h,
D.High_24h,
D.BestBid,
D.BestAsk
FROM Currencies C
INNER JOIN CryptoMarketsMaster M ON C.CryptoMarketId = C.CryptoMarketId
LEFT JOIN (SELECT ROW_NUMBER() over (partition by ProductId ORDER BY PriceDate DESC) as RN,Price,Open_24h,Volume_24h,Low_24h,High_24h,BestBid,BestAsk,ProductId FROM CurrencyRates ) D ON D.RN=1 AND D.ProductId=C.Id

Best Regards,

Will

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM