优化复杂的存储过程

时间:2019-01-27 14:02:59

标签: sql sql-server

我有一个非常复杂的存储过程,但我的SQL不那么强,请任何具有强大SQL专业知识并可以帮助我进行优化或至少可以给我一个提示的人,该过程将从数据库中选择收件箱消息针对特定用户,它包含许多其他参数,例如分页和类别以及语言输入和许多其他详细信息:

ALTER PROCEDURE [dbo].[Inbox]

    @ConfidentialityIds NVARCHAR(100) = '0,1,2,3',
    @UrgencyIds NVARCHAR(100) = '0,1,2,3',
    @CorrespondenceCategoryIds NVARCHAR(100) = '1,2,3,5,6,7',
    @CorrespondenceExtendedCategoryIds NVARCHAR(MAX),
    @IsPrivate bit = 0,
    @IsSaved bit = 0,
    @Importantance VARCHAR(10) = '0, 1',
    @UserId uniqueidentifier,
    @SelectedPage int = 1,
    @PageSize int = 25,
    @Now bigint,
    @IsImpersonated bit,
    @ActualLoggedInUserId uniqueidentifier,
    @IsEnglish bit,
    @OnlyArchived bit = null,
    @replaceNameWithEntName bit,
    @entityIds nvarchar(MAX),
    @OnlyLate bit = 0,
    @Statuses NVARCHAR(100) ='1,2,3,4,5',
    @ApplyPageFilter bit = 1,
    @IsBundled int,
    @showArchivedInCCInbox bit = 0,
    @appModuleId    INT = 0
    WITH RECOMPILE
As

BEGIN

SET transaction isolation level read uncommitted

DECLARE @lFirstRec INT, @lLastRec INT, @lTotalRows INT

SET @lFirstRec = ( @SelectedPage - 1 ) * @PageSize
SET @lLastRec = ( @SelectedPage * @PageSize + 1 )
SET @lTotalRows = @lFirstRec - @lLastRec + 1

DECLARE @isPersonalDelegationAvailable BIT = 0

IF EXISTS(
    SELECT 1
    FROM DelegatedToEntityUsers d
    WHERE d.DelegatedToUserId = @ActualLoggedInUserId 
    AND d.DelegatedFromUserId = @UserId 
    AND 
    (
        d.DelegatedToEntityId IS NULL OR d.DelegationType = 1
    ))
BEGIN
    SET @isPersonalDelegationAvailable = 1
END

DECLARE @tblEntities TABLE(Value INT)
INSERT INTO @tblEntities
SELECT Value FROM SplitCommaUniqueValues(@entityIds)

Select * from (
Select (ROW_NUMBER() OVER (ORDER BY K.ActionDate DESC, K.CorrespondenceDate DESC)) AS RowIndex,
Count(*) over () AS TotalCount,* 
from (
select (ROW_NUMBER() OVER (PARTITION BY CorrespondenceID Order by CorrespondenceID DESC)) AS CorrId, * 
from (
SELECT Distinct * FROM 
(
    SELECT 

    CONVERT(VARCHAR(100), R.CorrespondenceActionRecipientID) Id,
    A.CorrespondenceActionID ActionId,
    (CASE WHEN R.RecipientType IS NULL THEN NULL ELSE CAST(RecipientType AS INT) END) RecipientType,
    A.ActionTypeId,
    (CASE when @IsEnglish = 1 then ATypes.FriendlyTextEN else ATypes.FriendlyTextAR end) ActionTypeName,
    A.ActionCreatedByUserID SentById,

    CASE 
            when @replaceNameWithEntName = 0 then ISNULL(ActionCreatedByUser.ShortName, ActionCreatedByUser.EmployeeName)
            when @replaceNameWithEntName = 1 and SentByEntity.EntityID not in (SELECT Value FROM @tblEntities) then case when @IsEnglish = 1 then SentByEntity.EntityNameEn else SentByEntity.EntityNameAR end
            when @replaceNameWithEntName = 1 and SentByEntity.EntityID in (SELECT Value FROM @tblEntities) then ISNULL(ActionCreatedByUser.ShortName, ActionCreatedByUser.EmployeeName)
    END SentByFrom,


    A.WithDelegateFromUserID OnBehalfOfId,
    ISNULL(WithDelegateFromUser.ShortName, WithDelegateFromUser.EmployeeName) OnBehalfOfName,
    R.UserId SentToId,
    CASE 
        when @replaceNameWithEntName = 0 then ISNULL(SentToUser.ShortName, SentToUser.EmployeeName)
        when @replaceNameWithEntName = 1 and SentToEntity.EntityID not in (SELECT Value FROM @tblEntities) then case when @IsEnglish = 1 then SentToEntity.EntityNameEn else SentToEntity.EntityNameAR end
        when @replaceNameWithEntName = 1 and SentToEntity.EntityID in (SELECT Value FROM @tblEntities) then isnull(ISNULL(SentToUser.ShortName, SentToUser.EmployeeName), case when @IsEnglish = 1 then SentToEntity.EntityNameEn else SentToEntity.EntityNameAR end)
    END SentToName,

    R.EntityID SentToEntityId,
    SentToEntity.EntityNameAR SentToEntityNameAR,
    SentToEntity.EntityNameEN SentToEntityNameEN,
    R.Seen,
    (CASE WHEN MR.CorrespondenceActionRecipientID IS NOT NULL THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END) IsReadByUser,

    CAST(ISNULL(FollowedByUser.IsFollowedByUser, 0) AS BIT) IsFollowedByUser,
    (
        CASE WHEN EXISTS(SELECT 1 FROM CorrespondenceFollowups 
        WHERE CorrespondenceID = C.CorrespondenceID
        AND UserId  =  @UserId AND AssignedByUserId IS NOT NULL) THEN CAST(1 AS BIT)
        ELSE CAST(0 AS BIT) END
    ) IsAssignedFollowToUser,
    (
        CASE WHEN EXISTS(SELECT 1 FROM CorrespondenceFollowups 
        WHERE CorrespondenceID = C.CorrespondenceID
        AND AssignedByUserId  =  @UserId) THEN CAST(1 AS BIT)
        ELSE CAST(0 AS BIT) END
    ) IsAssignedFollowByUser,
    A.CorrespondenceID,
    A.ActionDate,
    A.ActionDeadlineDate,
    C.CompletionDate,
    C.CorrespondenceDeadlineDate CorrDeadlineDate,
    C.OwnerUserID CorrOwnerId,
    C.ChildNo ChildNo,
    OwnerUser.EmployeeName CorrOwnerName,
    C.Important,
    C.UrgencyId,
    C.LetterCorrespondenceId,
    (CASE when @IsEnglish = 1 then U.TextEN else U.TextAR end) UrgencyText,
    C.ConfidentialityId,
    (CASE when @IsEnglish = 1 then Confid.TextEN else Confid.TextAR end) ConfidentialityText,
    C.CorrespondenceCategoryId CategoryId,
    C.CorrespondenceClassificationID CorrespondenceClassificationID,
    (CASE when @IsEnglish = 1 then CCat.TextEN else CCat.TextAR end) CategoryName,
    CCat.ColorClass ColorClass,
    C.Subject,
    c.CorrespondenceFormula,
    C.InternalSenderEntityId,
    C.InternalRecipientEntityId,
    C.[Sequence] [Sequence],
    C.Year,
    C.CompletionStatus Status,
    Null Number,
    (CASE WHEN (
                (
                    (A.ActionDeadlineDate IS NOT NULL AND A.ActionDeadlineDate < @Now) 
                    OR
                    (C.CorrespondenceDeadlineDate IS NOT NULL AND C.CorrespondenceDeadlineDate < @Now) 
                )
                AND 
                C.[Closed-Archived] = 0) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END) IsLate,
    CAST(0 AS BIT) HasAnyEvents,
    C.CreatedByUserId,
    CreatedByUser.EmployeeName CreatedByUserName,
    CAST(C.CorrespondenceDate AS VARCHAR(50)) CorrDate,
    C.CorrespondenceDate,
    C.[Closed-Archived] ClosedArchived,
    C.IsSaved SavedActionTaken,
    ((CASE WHEN C.Important = 1 THEN CASE WHEN @IsEnglish = 1 THEN N'Important' ELSE N'هامة' END ELSE '' END) + (CASE WHEN C.Important = 1 AND C.UrgencyID <> 0 THEN CASE WHEN @IsEnglish = 1 THEN N' and ' ELSE N' و ' END ELSE '' END) + (CASE WHEN C.UrgencyID <> 0 THEN (CASE when @IsEnglish = 1 then U.TextEN else U.TextAR end) ELSE '' END)) ImportantUrgencyText,
    CAST(C.IsAutoSaved AS BIT) IsAutoSaved,
    -- *******************************************************************
    rem.ReminderDate as CorrespondenceReminderDateTime,
    remAction.ReminderDate as ActionReminderDateTime
    FROM (
            SELECT * FROM Correspondences CC
            WHERE CC.IsDeleted = 0
            AND CC.LetterCorrespondenceId IS NULL
            AND (CC.ConfidentialityId IN (SELECT [Value] FROM SplitCommaUniqueValues(@ConfidentialityIds)))
            AND 
            (   @IsPrivate = 0 OR
                (
                    @IsPrivate = 1 AND CC.IsForPresident = 1
                )
            )
            AND 
            (
                (CC.IsSaved = case when  @IsSaved =1 then 1 else CC.IsSaved end)
            ) 
            AND (@appModuleId = 0 OR CC.AppModuleId = @appModuleId)
        AND (CC.UrgencyID IN (SELECT value FROM SplitCommaUniqueValues(@UrgencyIds)))
        AND (CC.Important IN (SELECT value FROM SplitCommaUniqueValues(@Importantance)))
       AND CC.CompletionStatus IN(SELECT value FROM SplitComma(@Statuses))

        ) C
    LEFT JOIN CorrespondenceExtendedDetails CorrExt
        ON CorrExt.CorrespondenceID = C.CorrespondenceID

    LEFT JOIN CorrespondenceActions A 
        ON C.CorrespondenceID = A.CorrespondenceID
        AND A.IsDeleted = 0
        AND A.ActionTypeID != 7 -- إنهاء التذكير

    LEFT JOIN CorrespondenceActionRecipients R
        ON A.CorrespondenceActionID = R.CorrespondenceActionID
        AND (
                R.AsCopy = 1 
            )
    JOIN Urgencies U 
        ON C.UrgencyID = U.ID
    JOIN ActionTypes ATypes
        ON A.ActionTypeID = ATypes.ID
    JOIN CorrespondenceCategories CCat
        ON C.CorrespondenceCategoryId = CCat.ID
    JOIN Confidentialities Confid
        ON C.ConfidentialityID = Confid.ID
    LEFT JOIN Users ActionCreatedByUser
        ON A.ActionCreatedByUserID = ActionCreatedByUser.UserId
    LEFT JOIN Users WithDelegateFromUser
        ON A.WithDelegateFromUserID = WithDelegateFromUser.UserID
    LEFT JOIN Entities SentByEntity
        ON A.ActionCreatedByUserEntityId = SentByEntity.EntityID
    LEFT JOIN Users SentToUser
        ON R.UserId = SentToUser.UserId
    LEFT JOIN Entities SentToEntity
        ON R.EntityID = SentToEntity.EntityID
    LEFT JOIN Users OwnerUser
        ON C.OwnerUserID = OwnerUser.UserId
    LEFT JOIN Users CreatedByUser
        ON C.CreatedByUserID = CreatedByUser.UserId
    LEFT  JOIN MarkAsReads MR
        ON R.CorrespondenceActionRecipientID = MR.CorrespondenceActionRecipientID
        AND MR.UserId = @UserId
      OUTER APPLY 
                    (
                           SELECT TOP 1 1 IsFollowedByUser
                           FROM CorrespondenceFollowups CF 
                           WHERE CF.CorrespondenceId = C.CorrespondenceID
                           AND CF.UserId = @UserId
                           AND CF.AssignedByUserId IS NULL
                    ) FollowedByUser
    -- *******************************************************************
    LEFT JOIN LinkedCorrespondenceSchedules CS on  CS.CorrespondenceID = C.CorrespondenceID
    LEFT JOIN Reminder rem on rem.ReferenceId=C.CorrespondenceID AND rem.ReferenceType = 1 AND rem.CreatedByUserId=@UserId AND (rem.[Status] = 1 OR rem.[Status] = 2)
    Left JOIN Reminder remAction on remAction.ReferenceId = A.CorrespondenceActionID AND remAction.ReferenceType = 2 AND remAction.CreatedByUserId=@UserId AND (remAction.[Status] = 1 OR remAction.[Status] = 2)
    -- *******************************************************************
 WHERE  (
            (C.CorrespondenceCategoryId IN (SELECT Value FROM SplitComma(@CorrespondenceCategoryIds)) AND CorrExt.CorrespondenceExtendedCategoryId IS NULL)
            OR (CorrExt.CorrespondenceExtendedCategoryId IN (SELECT Value FROM SplitComma(@CorrespondenceExtendedCategoryIds)))
        )
        AND
        (
            -- Personal
            (
                (
                    (@IsImpersonated = 0 AND R.UserId = @UserId)
                    OR
                    (@IsImpersonated = 1 AND R.UserId = @UserId AND @isPersonalDelegationAvailable = 1)
                )
                AND R.RecipientType = 1 AND R.UserId Is Not null
            )
            OR
            -- Me as Manager (Impersonation mode handled from code by sending the proper Entity Ids.
            (
                (R.EntityID IN (SELECT Value FROM @tblEntities) AND R.EntityID Is Not null AND R.RecipientType != 1)
            )
        ) 
   AND C.[Closed-Archived] = Case When @showArchivedInCCInbox = 1 Then 0 Else C.[Closed-Archived] End
   AND R.UserTokeAction = 0 
   AND NOT EXISTS (
    SELECT 1 FROM Correspondences CC 
        INNER JOIN CorrespondenceLinks CL
            ON CC.CorrespondenceID = CL.LinkedCorrespondenceID AND CC.CorrespondenceID = C.CorrespondenceID AND CL.LinkTypeID = @IsBundled
   )
) T
WHERE T.LetterCorrespondenceId is null 
) as ttt
    ) K where CorrId = 1
    )N where (@ApplyPageFilter = 0 OR ( RowIndex > @lFirstRec AND RowIndex < @lLastRec))
Order by 
    ActionDate DESC, CorrespondenceDate
    option(recompile)
END

0 个答案:

没有答案