Home > Enterprise >  Subquery with TOP performing poorly
Subquery with TOP performing poorly

Time:11-26

Ok I have a performance problem in SQL function. I have query like this:

SELECT
    Number,
    (SELECT TOP 1 Value 
     FROM Table_B 
     WHERE Table_B.Number = Table_A.Number 
     ORDER BY ID DESC)
FROM 
    Table_A

I want see all records from Table_A with the TOP 1 record from Table_B

CodePudding user response:

You may try adding the following index to Table_B:

CREATE INDEX idx_b ON Table_B (Number, ID) INCLUDE (Value);

This index should let the Number lookup be fast, and should allow the first Value, as sorted by the ID, to be found. We include Value at the end of the index since it is used in the select, but not needed in the index itself.

CodePudding user response:

Use ROW_NUMBER() for serializing value with id desc and then LEFT JOIN main table with matching number and retrieve only first record from subquery result. LEFT JOIN is used here because table_B have no value for a number but as per requirement corresponding value of table_A must come.

-- SQL Server
SELECT a.Number
     , b.value
FROM Table_A a
LEFT JOIN (SELECT Number, ID, value
                , ROW_NUMBER() OVER (PARTITION BY Number, ID ORDER BY id DESC) row_num
           FROM Table_B) b         
       ON a.Number = b.Number
      AND b.row_num = 1

CodePudding user response:

WITH CTE_Table_B
AS(
    SELECT
        x.[ID],
        x.[Value],
        x.[Number]
    FROM(
        SELECT
            [ID]
            [Value],
            [Number],
            DENSE_RANK() OVER(PARTITION BY [Number] ORDER BY [ID] DESC) AS [Ranking]
        FROM Table_B
    ) AS x
    WHERE (1=1)
        AND x.[Ranking] = 1
)

SELECT
    a.[Number],
    b.[Value] 
FROM Table_A AS a

LEFT JOIN CTE_Table_B AS b
    ON b.[Number] = a.[Number]

CodePudding user response:

This is the "first in group" method that SMor mentions:

WITH cte AS
(
   SELECT a.Number,
          b.Value, 
          ROW_NUMBER() OVER (PARTITION BY a.Number ORDER BY b.ID DESC) AS rn
   FROM Table_A a
   LEFT OUTER JOIN Table_B b ON a.Number = b.Number
)
SELECT Number, Value
FROM cte
WHERE rn = 1 

CodePudding user response:

How about just using CROSS APPLY (assuming there will always be a match - if not use OUTER APPLY):

SELECT
    Number, tb.Value
FROM 
    Table_A
CROSS APPLY
    (SELECT TOP 1 Value 
     FROM Table_B 
     WHERE Table_B.Number = Table_A.Number 
     ORDER BY ID DESC) AS tb
  • Related