question

HennieF avatar image
HennieF asked

SQL Query Optimization

I have this query, it returns 570 rows, but runs 2m 35s. In SQL the query execute, but in my solution, it gives a timeout. How can I optimize this to run under 1m, pref 30s. SELECT [Region] = Region.FirstName, [Patient] = Patient.Name, [PatientStatus] = AccountRating.Name, [MedicalAid] = AccountType.Name, [QuoteAmount] = ( SELECT TOP 1 A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5966 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.SubscriberID = 240 AND Q.AccountID = Patient.AccountID ), [InvoiceAmount] = ( SELECT TOP 1 A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5969 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.SubscriberID = 240 AND Q.AccountID = Patient.AccountID ), [DateSubmitted] = ( SELECT TOP 1 A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5965 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.SubscriberID = 240 AND Q.AccountID = Patient.AccountID ), [DateApprovedDeclined] = ( SELECT TOP 1 A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5968 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.SubscriberID = 240 AND Q.AccountID = Patient.AccountID ), [IntAdmFormCreatedDate]= Q.DateCreated, [HasAdminForm] = 'Yes', [CreatedByUser] = PatientCreatedBy.Name FROM dbo.Account AS Patient JOIN dbo.AccountRating ON Patient.AccountRatingID = AccountRating.AccountRatingID JOIN dbo.AccountType ON Patient.AccountTypeID = AccountType.AccountTypeID JOIN dbo.[User] Region ON Patient.UserID = Region.UserID JOIN dbo.[User] PatientCreatedBy ON Patient.CreatedBy = PatientCreatedBy.UserID JOIN dbo.Questionnaire Q ON Patient.AccountID = Q.AccountID WHERE Patient.SubscriberID = 240 AND (Q.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102)))) AND Q.QuestionnaireDefinitionID = 235 AND Q.IsActive = 1 AND Region.FirstName <> 'Rubbish' UNION SELECT [Region] = Region.FirstName, [Patient] = Patient.Name, [PatientStatus] = AccountRating.Name, [MedicalAid] = AccountType.Name, [QuoteAmount] = '0', [InvoiceAmount] = '0', [DateSubmitted] = '', [DateApprovedDeclined] = '', [IntAdmFormCreatedDate] = '', [HasAdminForm] = 'No', [CreatedByUser] = PatientCreatedBy.Name FROM dbo.Account AS Patient JOIN dbo.AccountRating ON Patient.AccountRatingID = AccountRating.AccountRatingID JOIN dbo.AccountType ON Patient.AccountTypeID = AccountType.AccountTypeID JOIN dbo.[User] AS Region ON Patient.UserID = Region.UserID JOIN dbo.[User] AS PatientCreatedBy ON Patient.CreatedBy = PatientCreatedBy.UserID WHERE NOT EXISTS( SELECT * FROM Questionnaire AS Q WHERE Patient.AccountID = Q.AccountID AND Q.QuestionnaireDefinitionID = 235 AND Patient.SubscriberID = 240 AND Q.SubscriberID = 240 ) AND Patient.SubscriberID = 240 AND Patient.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102))) AND Region.FirstName <> 'Rubbish' Here is another version of the query I tried, but also runs the same time. SELECT [Region] = Region.FirstName, [Patient] = Patient.Name, [PatientStatus] = AccountRating.Name, [MedicalAid] = AccountType.Name, [QuoteAmount] = Q1.Response, [InvoiceAmount] = Q2.Response, [DateSubmitted] = Q3.Response, [DateApprovedDeclined] = Q4.Response, [IntAdmFormCreatedDate]= Q.DateCreated, [HasAdminForm] = 'Yes', [CreatedByUser] = PatientCreatedBy.Name FROM dbo.Account AS Patient JOIN dbo.AccountRating ON Patient.AccountRatingID = AccountRating.AccountRatingID JOIN dbo.AccountType ON Patient.AccountTypeID = AccountType.AccountTypeID JOIN dbo.[User] Region ON Patient.UserID = Region.UserID JOIN dbo.[User] PatientCreatedBy ON Patient.CreatedBy = PatientCreatedBy.UserID JOIN dbo.Questionnaire Q ON Patient.AccountID = Q.AccountID OUTER APPLY ( SELECT TOP 1 Q.AccountID, A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5966 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 Q.SubscriberID = 240 AND Q.AccountID = Patient.AccountID ) Q1 OUTER APPLY ( SELECT TOP 1 Q.AccountID, A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5969 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.AccountID = Patient.AccountID ) Q2 OUTER APPLY ( SELECT TOP 1 Q.AccountID, A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5965 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.AccountID = Patient.AccountID ) Q3 OUTER APPLY ( SELECT TOP 1 Q.AccountID, A.Response FROM dbo.Questionnaire Q JOIN dbo.QuestionnaireDefinition QRD ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID AND QRD.Name = 'Internal Admin' LEFT JOIN QuestionDefinition QD ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID AND QD.QuestionDefinitionID = 5968 LEFT OUTER JOIN Answer A ON A.QuestionnaireID = Q.QuestionnaireID AND A.QuestionDefinitionID = QD.QuestionDefinitionID WHERE Q.IsActive = 1 AND Q.AccountID = Patient.AccountID ) Q4 WHERE Patient.SubscriberID = 240 AND (Q.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102)))) AND Q.QuestionnaireDefinitionID = 235 AND Q.IsActive = 1 AND Region.FirstName <> 'Rubbish' UNION SELECT [Region] = Region.FirstName, [Patient] = Patient.Name, [PatientStatus] = AccountRating.Name, [MedicalAid] = AccountType.Name, [QuoteAmount] = '0', [InvoiceAmount] = '0', [DateSubmitted] = '', [DateApprovedDeclined] = '', [IntAdmFormCreatedDate] = '', [HasAdminForm] = 'No', [CreatedByUser] = PatientCreatedBy.Name FROM dbo.Account AS Patient JOIN dbo.AccountRating ON Patient.AccountRatingID = AccountRating.AccountRatingID JOIN dbo.AccountType ON Patient.AccountTypeID = AccountType.AccountTypeID JOIN dbo.[User] AS Region ON Patient.UserID = Region.UserID JOIN dbo.[User] AS PatientCreatedBy ON Patient.CreatedBy = PatientCreatedBy.UserID WHERE NOT EXISTS( SELECT * FROM Questionnaire AS Q WHERE Patient.AccountID = Q.AccountID AND Q.QuestionnaireDefinitionID = 235 AND Patient.SubscriberID = 240 AND Q.SubscriberID = 240 ) AND Patient.SubscriberID = 240 AND Patient.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102))) AND Region.FirstName <> 'Rubbish'
querysql queryoptimizationsqlserver2008optimizer
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

ThomasRushton avatar image ThomasRushton ♦♦ commented ·
Can you share the query plan?
1 Like 1 ·

1 Answer

·
ThomasRushton avatar image
ThomasRushton answered
Without seeing the query plan, it's difficult to know where to begin. However, I would suggest changing the various ...DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102)))... statements by calculating that value up front: DECLARE @WhateverDate DateTime SELECT @WhateverDate = DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102))) Then change your query to use `@WhateverDate` instead of that big dateadd/datediff/getdate/convert statement. That might help a bit. Apart from anything, it'll help the readability and maintainability, given that you've got that clause in twice...
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.