Reputation: 7994
I have this query
DECLARE @Company VARCHAR(20) = 'ABC'
DECLARE @Train INT = 1
SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L
INNER JOIN vemd_episodes E ON E.Company = L.Company
AND E.cpid = L.cpid
AND E.dDate = L.dDate
WHERE L.Company = @Company
AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 1)
OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 0))
It takes forever to finish.
After 1 minute it only retrieve 400 records and is still running.
Total number of records this query should fetch is around 500,000 records.
But when I hard code the parameters in the query
SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L
INNER JOIN vemd_episodes E ON E.Company = L.Company
AND E.cpid = L.cpid
AND E.dDate = L.dDate
WHERE L.Company = 'ABC'
AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND 1 = 1)
OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND 1 = 0))
it is extremely fast and retrieves 500k records in 16 seconds.
Why is using parameters in the where
clause causing this issue? And how to fix it?
Edit :
I could not keep it running till the end
so I select top 1000 and got execution plan
Upvotes: 0
Views: 190
Reputation: 1269633
Try using window functions:
SELECT L.*
FROM (SELECT L.*,
MAX(census_datetime) OVER () as max_census_datetime
FROM vemd_episodes_firstnet_currentPatients L
) L JOIN
vemd_episodes E
ON E.Company = L.Company AND
E.cpid = L.cpid AND
E.dDate = L.dDate
WHERE L.Company = @Company AND
((census_datetime <> max_census_datetime AND @Train = 1) OR
(census_datetime = max_census_datetime AND @Train = 0)
);
The optimizer should find it easier to generate an appropriate execution plan with a simpler where
clause.
Upvotes: 2
Reputation: 13393
You can try the query with the recompile option OPTION (RECOMPILE)
With parameterized queries, SQL sometimes chooses the wrong execution plan and insist to use it.
DECLARE @Company VARCHAR(20) = 'ABC'
DECLARE @Train INT = 1
SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L
INNER JOIN vemd_episodes E ON E.Company = L.Company
AND E.cpid = L.cpid
AND E.dDate = L.dDate
WHERE L.Company = @Company
AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 1)
OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 0))
OPTION (RECOMPILE)
Upvotes: 4