0

我有這個查詢,它返回570行,但運行2米35秒。在SQL中查詢執行,但在我的解決方案中,它給出了超時。我怎樣才能優化這個運行在1米以下,30秒前。聯合選擇SQL查詢優化

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' 

這裏是我試過的另一個版本的查詢,但也運行同一時間。

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' 
+0

我建議你問另一個問題。描述您正在嘗試解決的問題以及您正在使用的數據。你的查詢看起來太複雜了。 –

+0

@GordonLinoff,我試圖優化我的查詢,dnoeth幫助了我,並且我解決了它。非常感謝您的反饋 – Hennie

回答

2

您的標量子查詢都共享相同的連接,只是QD.QuestionDefinitionID不同。

您可以重寫這些4件上衣與一個派生表,並加入到它,而不是:

... 
LEFT JOIN 
(
    SELECT 
     Q.AccountID, 
     MAX(CASE WHEN QD.QuestionDefinitionID = 5966 THEN A.Response END) AS [DateSubmitted] 
     MAX(CASE WHEN QD.QuestionDefinitionID = 5968 THEN A.Response END) AS [DateApprovedDeclined] 
     ... 
    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 
    LEFT OUTER JOIN Answer A 
     ON A.QuestionnaireID = Q.QuestionnaireID 
     AND A.QuestionDefinitionID = QD.QuestionDefinitionID 
    WHERE Q.IsActive = 1 
    AND Q.SubscriberID = 240 
    GROUP BY Q.AccountID 
) AS Q 
ON Q.AccountID = Patient.AccountID 

我用MAX,因爲你沒有ORDER BY在你的子查詢,因此,其準確值要麼沒有按」或者每個值只有一行。

+0

哇這是一個很好的結合查詢的方式......感謝這一點。 – Hennie

+0

我的查詢花了38s,但仍然超時,會嘗試優化更多,但主要感謝您的努力! – Hennie

+0

@亨尼:您可能需要添加一些索引。分別運行兩個SELECT並檢查性能。您可以切換到UNION ALL以避免DISTINCT處理(但我不認爲這會實際上改善時間) – dnoeth