为什么这个SQL Server查询这么慢?

时间:2018-04-19 14:42:48

标签: sql sql-server

此查询需要4秒才能运行,并返回大约62000行。 @c,@ p和@a是由int组成的字符串,以逗号分隔或为空,基于需要过滤的内容...遗憾的是,这不能更改。

我试图在没有过滤器的情况下运行它并且它没有任何区别。 我对SQL很新。

3个公用表表达式用于删除额外的代码行。

我希望能够在一秒钟内运行,如果可能的话

DECLARE @UId int = '817',
        @c varchar(max) = '',
        @p varchar(max) = '',
        @a varchar(max) = ''

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF OBJECT_ID('tempdb..#FilteredData') IS NOT NULL 
     DROP TABLE #FilteredData;

WITH cteuag AS 
(
    SELECT
        uag.CId,
        uag.AuthorIsatIonGroupId,
        rn = ROW_NUMBER() OVER (PARTITION BY uag.[UId], uag.CId, uag.AuthorIsatIonGroupId ORDER BY uag.CId)
    FROM 
        uag
    WHERE 
        uag.[UId] = @UId
        AND uag.IsDeleted = 0
        AND (@c = '' OR (@c LIKE CONVERT(varchar(4), uag.CId)
                         OR @c LIKE '%,' + CONVERT(varchar(4), uag.CId) + ',%'
                         OR @c LIKE CONVERT(varchar(4), uag.CId) + ',%'
                         OR @c LIKE '%,' + CONVERT(varchar(4), uag.CId))
            )
),
cteuc AS
(
    SELECT
        uc.CId,
        cteuag.AuthorIsatIonGroupId,
        uc.[UId],
        i.FirstName + Iif(i.MiddleName IS NOT NULL, ' ' + i.MiddleName + ' ', ' ') + i.Surname AS [AName],
        rn = ROW_NUMBER() OVER (PARTITION BY uc.CId, uc.[UId] ORDER BY uc.ModifiedAt)
    FROM 
        uc
    INNER JOIN 
        cteuag ON cteuag.CId = uc.CId
               AND uc.IsDeleted = 0
               AND (@a = '' OR (@a LIKE CONVERT(varchar(4), uc.[UId])
                                OR @a LIKE '%,' + CONVERT(varchar(4), uc.[UId]) + ',%'
                                OR @a LIKE CONVERT(varchar(4), uc.[UId]) + ',%'
                                OR @a LIKE '%,' + CONVERT(varchar(4), uc.[UId]))
                   )
    INNER JOIN 
        ui ON ui.[UId] = uc.[UId]
           AND ui.IsDeleted = 0
    INNER JOIN 
        i ON i.PId = ui.IndividualId
),
ctel AS
(
    SELECT
        la.LId,
        p.CId,
        la.[UId],
        rn = ROW_NUMBER() OVER (PARTITION BY la.LId ORDER BY la.DateUpdated DESC)
    FROM  
        la 
    INNER JOIN 
        p ON p.Id = la.PId
          AND p.IsDeleted = 0
          AND la.IsDeleted = 0
          AND la.[UId] IS NOT NULL
    INNER JOIN 
        l ON la.LId = l.Id
          AND l.IsDeleted = 0
)
SELECT
    c.Id AS CId,
    c.[Name] AS CName,
    u.Id AS AId,
    cteuc.AName AS AName,
    ctel.LId AS LId,
    qh.Id AS QhId,
    q.Id AS QId,
    q.IsTrue AS isTrue,
    p.Id AS PId,
    p.[Name] AS PName,
    qi.FinalCalculation AS Calculation
INTO 
    #FilteredData
FROM 
    c
INNER JOIN 
    cteuc ON cteuc.CId = c.Id
          AND cteuc.Rn = 1
          AND c.IsDeleted = 0
LEFT OUTER JOIN 
    u ON u.Id = Iif(cteuc.AuthorIsatIonGroupId = 1, @UId, cteuc.[UId])
      AND u.IsDeleted = 0
LEFT OUTER JOIN 
    ctel ON ctel.CId = c.Id
         AND ctel.Rn = 1
         AND ctel.[UId] = u.Id
LEFT OUTER JOIN 
    (la
        INNER JOIN 
            qla ON qla.LeadActivityId = la.Id
                AND la.IsDeleted = 0
                AND la.ActivityTypeId = 4
        INNER JOIN 
            qh ON qla.QhId = qh.Id
               AND qh.IsDeleted = 0
               AND qh.IsReRated = 0
        LEFT OUTER JOIN 
            (q 
             INNER JOIN 
                 p ON p.Id = q.PId
                   AND q.IsDeleted = 0
                   AND p.IsDeleted = 0
        ) ON q.QhId = qh.Id) ON la.[UId] = u.Id
        AND la.LId = ctel.LId
        AND 
        (
            @p = ''
            OR 
            (
                @p LIKE CONVERT(varchar(4), p.Id)
                OR @p LIKE '%,' + CONVERT(varchar(4), p.Id) + ',%'
                OR @p LIKE CONVERT(varchar(4), p.Id) + ',%'
                OR @p LIKE '%,' + CONVERT(varchar(4), p.Id)
            )
        )
    LEFT OUTER JOIN 
    (
        SELECT
            qi1.QId,
            SUM(Iif(qi1.Calculation = 0, 0, qi1.Calculation + qi1.Extra)) AS FinalCalculation
        FROM qi
        WHERE qi1.IsDeleted = 0
        GROUP BY QId
    ) AS qi ON qi.QId = q.Id
WHERE 
    (
        @p = ''
        OR 
        (
            p.Id IS NOT NULL
            OR qh.Id IS NULL
        )
    )

SELECT * FROM #FilteredData

修改

为了清楚起见,上面的查询运行速度不比这个慢:

DECLARE @UId int = '817'

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF OBJECT_ID('tempdb..#FilteredData') IS NOT NULL DROP TABLE #FilteredData;

WITH cteuag AS 
(
    SELECT
        uag.CId,
        uag.AuthorIsatIonGroupId,
        rn = ROW_NUMBER() OVER (PARTITION BY uag.[UId], uag.CId, uag.AuthorIsatIonGroupId ORDER BY uag.CId)
    FROM uag
    WHERE uag.[UId] = @UId
        AND uag.IsDeleted = 0
),
cteuc AS
(
    SELECT
        uc.CId,
        cteuag.AuthorIsatIonGroupId,
        uc.[UId],
        i.FirstName + Iif(i.MiddleName IS NOT NULL, ' ' + i.MiddleName + ' ', ' ') + i.Surname AS [AName],
        rn = ROW_NUMBER() OVER (PARTITION BY uc.CId, uc.[UId] ORDER BY uc.ModifiedAt)
    FROM uc
        INNER JOIN cteuag ON cteuag.CId = uc.CId
            AND uc.IsDeleted = 0
        INNER JOIN ui ON ui.[UId] = uc.[UId]
            AND ui.IsDeleted = 0
        INNER JOIN i ON i.PId = ui.IndividualId
),
ctel AS
(
    SELECT
        la.LId,
        p.CId,
        la.[UId],
        rn = ROW_NUMBER() OVER (PARTITION BY la.LId ORDER BY la.DateUpdated DESC)
    FROM la 
        INNER JOIN p ON p.Id = la.PId
            AND p.IsDeleted = 0
            AND la.IsDeleted = 0
            AND la.[UId] IS NOT NULL
        INNER JOIN l ON la.LId = l.Id
            AND l.IsDeleted = 0
)
SELECT
    c.Id AS CId,
    c.[Name] AS CName,
    u.Id AS AId,
    cteuc.AName AS AName,
    ctel.LId AS LId,
    qh.Id AS QhId,
    q.Id AS QId,
    q.IsTrue AS isTrue,
    p.Id AS PId,
    p.[Name] AS PName,
    qi.FinalCalculation AS Calculation
INTO #FilteredData
FROM c
    INNER JOIN cteuc ON cteuc.CId = c.Id
        AND cteuc.Rn = 1
        AND c.IsDeleted = 0
    LEFT OUTER JOIN u ON u.Id = Iif(cteuc.AuthorIsatIonGroupId = 1, @UId, cteuc.[UId])
        AND u.IsDeleted = 0
    LEFT OUTER JOIN ctel ON ctel.CId = c.Id
        AND ctel.Rn = 1
        AND ctel.[UId] = u.Id
    LEFT OUTER JOIN 
    (
        la
        INNER JOIN qla ON qla.LeadActivityId = la.Id
            AND la.IsDeleted = 0
            AND la.ActivityTypeId = 4
        INNER JOIN qh ON qla.QhId = qh.Id
            AND qh.IsDeleted = 0
            AND qh.IsReRated = 0
        LEFT OUTER JOIN 
        (
            q 
            INNER JOIN p ON p.Id = q.PId
                AND q.IsDeleted = 0
                AND p.IsDeleted = 0
        ) ON q.QhId = qh.Id) ON la.[UId] = u.Id
        AND la.LId = ctel.LId
    LEFT OUTER JOIN 
    (
        SELECT
            qi1.QId,
            SUM(Iif(qi1.Calculation = 0, 0, qi1.Calculation + qi1.Extra)) AS FinalCalculation
        FROM qi
        WHERE qi1.IsDeleted = 0
        GROUP BY QId
    ) AS qi ON qi.QId = q.Id

SELECT * FROM #FilteredData

所以我知道它不是用作过滤器的逗号分隔值,也不是主要的外卡。

1 个答案:

答案 0 :(得分:0)

事实证明它在另一台笔记本电脑上运行良好,这意味着它与我的笔记本电脑有关。无论如何,看看评论,这个查询可以使用很多改进