Оптимизировать - выбрать, существует ли запись / условие в другой таблице -TSQL - PullRequest
0 голосов
/ 02 октября 2011
CREATE TABLE IntegrationLog (
IntegrationLogID INT IDENTITY(1,1) NOT NULL,
RecordID INT NOT NULL,
SyncDate DATETIME NOT NULL, 
Success BIT NOT NULL,
ErrorMessage VARCHAR(MAX) NULL,
PreviousError BIT NOT NULL --last sync attempt for record failed for syncdate
)

Моя цель здесь - вернуть каждое значение записи, сообщение об ошибке, за которым не последовал полный успех, исключить, где для записи было (Success == 1 и PreviousError == 0), которое произошло послев прошлый раз произошла эта ошибка.Для этого показателя я также хочу знать, был ли когда-либо успешный (частичный или иной) успех, который когда-либо происходил.

Или, другими словами, я хочу видеть ошибки и записи, которые они произошли в этом убежищене было исправлено с момента возникновения ошибки.Я также хочу знать, имел ли я когда-либо успех для конкретного recordid.

Это работает, но мне любопытно, есть ли лучший способ сделать это?

SELECT  errors.RecordID ,
        errors.errorMessage,
        CASE WHEN PartialSuccess.RecordID IS NOT NULL THEN 1
             ELSE NULL
        END AS Resolved
FROM    ( SELECT    errors.RecordID ,
                    errors.ErrorMessage ,
                    MAX(SyncDate) AS SyncDate
          FROM      dbo.IntegrationLog AS Errors
          WHERE     errors.Success = 0
          GROUP BY errors.RecordID ,
                    errors.ErrorMessage ,
                    errors.ErrorDescription
        ) AS Errors
        LEFT JOIN dbo.IntegrationLog AS FullSuccess ON FullSuccess.RecordID = Errors.RecordID
                                                              AND FullSuccess.Success = 1
                                                              AND FullSuccess.PreviousError = 0
                                                              AND FullSuccess.SyncDate > Errors.SyncDate
        LEFT JOIN ( SELECT  partialSuccess.RecordID
                    FROM    dbo.IntegrationLog AS partialSuccess
                    WHERE   partialSuccess.Success = 1
                    GROUP BY partialSuccess.RecordID
                  ) AS PartialSuccess ON Errors.RecordID = PartialSuccess.RecordID
WHERE   FullSuccess.RecordID IS NULL

Iтакже создал пастин с несколькими различными способами структурирования запроса.http://pastebin.com/FtNv8Tqw Есть ли еще один вариант?

Если это поможет, фоном для проекта является то, что я пытаюсь синхронизировать записи, которые были обновлены с момента их последней успешной синхронизации (частичная или полная), ирегистрировать попытки.Пакет записей идентифицируется для синхронизации.Каждая попытка записи регистрируется.Если это не удалось, в зависимости от ошибки, возможно, можно попытаться скопировать данные и повторить попытку.Для этой «работы» время, когда мы собрали записи, используется как SyncDate.Таким образом, для данной SyncDate у нас могут быть записи, которые были успешно синхронизированы с первой попытки, записи, от которых мы отказались с первой попытки, записи, которые мы массировали и смогли синхронизировать и т. Д. Каждая попытка заносится в журнал.

это что-то изменит, если вместо того, чтобы узнать, был ли достигнут какой-либо успех для этого идентификатора записи, я хочу определить, произошел ли частичный успех с момента последней ошибки.

Спасибо!Также приветствуются предложения по формулировке вопроса.

1 Ответ

1 голос
/ 02 октября 2011

Вы, вероятно, должны показать план запроса, взглянуть на то, на что тратится большая часть времени и соответствующим образом проиндексировать.

Тем не менее, вы можете попробовать использовать оконную функцию ROW_NUMBER вместо MAX.

WITH cte 
     AS (SELECT errors.recordid, 
                errors.errormessage, 
                CASE 
                  WHEN partialsuccess.recordid IS NOT NULL THEN 1 
                  ELSE NULL 
                END 
                   AS resolved, 
                Row_number() OVER (PARTITION BY errors.recordid ORDER BY 
                syncdate 
                DESC) 
                   rn 
         FROM   integrationlog error 
                LEFT JOIN integrationlog fullsuccess 
                  ON fullsuccess.recordid = errors.recordid 
                     AND fullsuccess.success = 1 
                     AND fullsuccess.previouserror = 0 
                     AND fullsuccess.syncdate > errors.syncdate 
                LEFT JOIN (SELECT partialsuccess.recordid 
                           FROM   dbo.integrationlog AS partialsuccess 
                           WHERE  partialsuccess.success = 1 
                           GROUP  BY partialsuccess.recordid) AS partialsuccess 
                  ON errors.recordid = partialsuccess.recordid 
         WHERE  errors.success = 0) 
SELECT 
     recordid,
     errormessage,
      resolved
FROM   cte 
WHERE  rn = 1 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...