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
)
我的目标是返回每个记录,即没有完全成功的erorrmessage,排除在上一次之后发生的记录(成功== 1和PreviousError == 0)的位置错误发生了。对于这个记录,我也想知道是否曾经发生过(部分或其他)成功。
或者换句话说,我希望看到自错误发生以来未修复的错误及其发生的记录。我也想知道我是否曾在特定记录中取得过成功。
这有效,但我很好奇是否有更好的方法来做到这一点?
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
我还用几种不同的方式创建了一个pastebin,用于构建查询。 http://pastebin.com/FtNv8Tqw 还有其他选择吗?
如果有帮助,项目的背景是我正在尝试同步自上次成功同步(部分或完全)以来已更新的记录并记录尝试。识别出一批记录被同步的记录。记录每个记录尝试。如果失败,根据错误可能会尝试按摩数据并再次尝试。对于这个“工作”,我们收集记录的时间用作SyncDate。因此,对于给定的SyncDate,我们可能会在第一次尝试时成功同步的记录,我们在第一次尝试时放弃的记录,我们按摩的记录以及能够同步的记录等。每次尝试都会被记录。
如果不想知道该记录是否有任何成功,它是否会改变任何内容,我希望确定自上次错误发生以来是否已经发生了部分成功。
谢谢!关于我提出这个问题的建议也很受欢迎。
答案 0 :(得分:1)
您应该显示查询计划,看看大部分时间花在哪里并适当地编制索引。
那说你可以尝试的一件事就是使用Window函数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