SQL Server: query performance

JDias 161 Reputation points
2021-11-12T11:29:35.293+00:00

I would like to write a fast query returning the data that the following query returns:

SELECT M,COmb,Mod,Loc,Initial,
Final,Kms_,R,Franq,Num_Fleet,Pneus,Cli,Active,Interv,
Cost1,Cost2,Name,Colab_Cod,col.colName
FROM tFleetCars AS v
OUTER APPLY (
    SELECT TOP(1) Name FROM vFleetExpenses WHERE M=v.M ORDER BY Yr DESC, Mth DESC
) AS d (Name)
LEFT JOIN DB2.dbo.tCol AS col ON col.colID=Colab_Cod

This query returns about 400 lines but takes minutes to complete. If I remove the inner query (SELECT TOP(1) ...) the query only takes a few seconds.

How to make this query efficient? I would like to have a WHERE clause with a MAX, but this is imposible...

I am hoping that this query will take only a few seconds. I think the server where this query runs is very slow...

Note: Yr is year and Mth is month...

Developer technologies | Transact-SQL
Developer technologies | Transact-SQL
A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
SQL Server | Other
{count} votes

Answer accepted by question author
  1. Guoxiong 8,211 Reputation points
    2021-11-12T15:34:55.183+00:00

    Try this:

    ;WITH CTE_vFleetExpenses AS (
        SELECT t.[Name], t.M
        FROM (
            SELECT [Name], M, ROW_NUMBER() OVER(PARTITION BY M ORDER BY Yr DESC, Mth DESC) AS RN
            FROM vFleetExpenses
        ) AS t
        WHERE t.RN = 1
    )
    
    SELECT v.M,COmb,Mod,Loc,Initial,
     Final,Kms_,R,Franq,Num_Fleet,Pneus,Cli,Active,Interv,
     Cost1,Cost2,d.Name,Colab_Cod,col.colName
     FROM tFleetCars AS v
    INNER JOIN CTE_vFleetExpenses AS d ON d.M = v.M
     LEFT JOIN DB2.dbo.tCol AS col ON col.colID=Colab_Cod
    
    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Erland Sommarskog 127.4K Reputation points MVP Volunteer Moderator
    2021-11-12T23:33:36.833+00:00

    If you are on a version recent enough, you can try to add this at the end:

    OPTION (USE HINT('DISABLE_OPTIMIZER_ROWGOAL'))
    

  2. EchoLiu-MSFT 14,621 Reputation points
    2021-11-15T07:11:21.113+00:00

    Hi @JDias ,

    Sometimes using OUTER APPLY will perform a clustered index scan, in order to optimize performance, consider using LEFT JOIN instead of OUTER APPLY:

        ;WITH cte  
        as(SELECT Name,ROW_NUMBER() OVER(PARTITION BY M ORDER BY Yr DESC, Mth DESC) rr  
        FROM vFleetExpenses )  
          
        SELECT v.M,COmb,Mod,Loc,Initial,  
         Final,Kms_,R,Franq,Num_Fleet,Pneus,Cli,Active,Interv,  
         Cost1,Cost2,Name,Colab_Cod,col.colName  
        FROM tFleetCars AS v  
        LEFT JOIN cte c ON v.M=c.M AND c.rr=1  
        LEFT JOIN DB2.dbo.tCol AS col ON col.colID=Colab_Cod  
    

    Since there is no relevant sample data to test, the above code is untested code. If this does not solve your problem, please share us your table structure (CREATE TABLE …) and some sample data(INSERT INTO …) ,So that we’ll get a right direction and make some test.

    Regards,
    Echo


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.