Подзапрос SQL выполняется очень быстро индивидуально, но при использовании в select очень медленно - PullRequest
0 голосов
/ 03 октября 2018

У меня есть набор таблиц, к которым я присоединяюсь, чтобы создать набор записей, а затем выполнить дополнительный выбор для набора некоторых записей.Запрос в коде используется в представлении как CTE.

При проверке только подзапроса он выполняется очень быстро, например, 0,01 - 0,02 с.То же самое относится и к тем временным таблицам, которые используются для извлечения записей.Поскольку я планирую использовать его внутри представления, решение для временной таблицы выходит за рамки.Обычный запрос выполняется вместо 37-50 минут.

SELECT 
 CallDate
,MediaChannel
,SubCategory
,Vendor
,BusinessVertical
,SUM(NumberOfLeads) AS NumberOfLeads
,CASE 
    WHEN SUM([CostPerLead]) <> 0
        THEN SUM([CostPerLead])
    ELSE NULL
    END AS Cost
,[CostPerLead]
,SourceName
,ParentLeadSource
,IsBillable
,dvce_type

FROM (
SELECT [PhoneLabel]
    ,[DialogTechCallId] = cd.DialogTechCallId
    ,[LeadId] = c.LeadId
    ,[CostPerLead] = CAST(cpl.cost AS INT)
    ,[SourceName] = bt.LeadCompany
    ,[ParentLeadSource] = ftlc.fruit
    ,[DialogTechPhoneNumber] = cd.CalledNumber
    ,[CallDate] = CAST(cd.[CallDateTime] AS DATE)
    ,[CallType] = cd.CallType
    ,[TalkTime] = cd.[TalkTimeMinutes]
    ,[TalkTimeSeconds] = CASE 
        WHEN ISNUMERIC(cd.[TalkTimeMinutes]) = 1
            THEN CAST(cd.[TalkTimeMinutes] AS DECIMAL(10, 2)) * 60
        ELSE 0
        END
    ,[TimeToQualify] = bt.Billabletime
    ,[IsBillable] = CASE 
        WHEN ISNUMERIC(cd.[TalkTimeMinutes]) = 1
            THEN CASE 
                    WHEN CAST(cd.[TalkTimeMinutes] AS DECIMAL(10, 2)) * 60 
    >= CAST(bt.Billabletime AS INT)
                        THEN 1
                    WHEN bt.Billabletime = 900
                        THEN 1
                    ELSE 0
                    END
        ELSE 0
        END
    ,[MediaChannel] = ftlc.channel2
    ,[SubCategory] = ftlc.sub
    ,[Vendor] = ftlc.vendor
    ,[BusinessVertical] = ftlc.business_vertical
    ,[NumberOfLeads] = 1
    ,[dvce_type] = ftlc.dvce_type

    FROM [dbo].[Abc] d WITH (NOLOCK)

    LEFT JOIN [dt].[cde] cd WITH (NOLOCK) ON d.FullDate = 
    CAST(cd.CallDateTime AS DATE)

    LEFT JOIN [dt].[efg] c WITH (NOLOCK) ON cd.DialogtechCallId = 
    c.DialogTechCallid

    INNER JOIN [dt].[hij] m WITH (NOLOCK) ON cd.CallerId = 
    m.DialogTechPhoneNumber

    INNER JOIN [dt].[klm] bt WITH (NOLOCK) ON m.LeadSourceInfoId = 
    bt.LeadSourceId AND cd.[CallDateTime] BETWEEN bt.[StartDateTime]
    AND ISNULL(bt.[EndDateTime], GETDATE())

    INNER JOIN [dbo].[jkl] ftlc WITH (NOLOCK) ON bt.ParentLeadSource = 
    ftlc.fruit

    INNER JOIN dbo.xyz cpl WITH (NOLOCK) ON ftlc.lead_company =        
    cpl.lead_company AND cd.[CallDateTime] >= cpl.[start_date]
    AND cd.[CallDateTime] <= ISNULL(cpl.[end_date], GETDATE())

    WHERE CAST(cd.[CallDateTime] AS DATE) >= '2018-08-01'
    AND CASE WHEN ISNUMERIC(cd.[TalkTimeMinutes]) = 1
            THEN CASE 
                    WHEN CAST(cd.[TalkTimeMinutes] AS DECIMAL(10, 2)) * 60 
    >= CAST(bt.Billabletime AS INT)
                        THEN 1
                    WHEN bt.Billabletime = 900
                        THEN 1
                    ELSE 0
                    END
        ELSE 0
        END = 1
   ) sub

 GROUP BY 
 CallDate
,MediaChannel
,SubCategory
,Vendor
,BusinessVertical
,SourceName
,ParentLeadSource
,IsBillable
,dvce_type
,CostPerLead;

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

1 Ответ

0 голосов
/ 03 октября 2018

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

Не зная ни структуры таблиц или функций, ни каких-либо фактических данных, я придумал следующую упрощенную версию:Ваш запрос.Он удаляет неиспользуемые столбцы из подзапроса, бесполезное объединение, упрощенные операторы CASE и удаление CostPerLead из основного запроса, поскольку вы агрегируете это.

SELECT
    CallDate
    ,MediaChannel
    ,SubCategory
    ,Vendor
    ,BusinessVertical
    ,NumberOfLeads   = COUNT(*)
    ,Cost            = NULLIF(SUM(CostPerLead), 0)
    ,SourceName
    ,ParentLeadSource
    ,IsBillable
    ,dvce_type
FROM
(



    SELECT
        CallDate            = CAST(cd.CallDateTime AS DATE)
        ,MediaChannel       = ftlc.channel2
        ,SubCategory        = ftlc.sub
        ,Vendor             = ftlc.vendor
        ,BusinessVertical   = ftlc.business_vertical
        ,CostPerLead        = CAST(cpl.cost AS INT)
        ,SourceName         = bt.LeadCompany
        ,ParentLeadSource   = ftlc.fruit
        ,IsBillable         = CASE WHEN ISNUMERIC(cd.TalkTimeMinutes) = 1
                                        AND (
                                                CAST(cd.TalkTimeMinutes AS DECIMAL(10, 2)) * 60 >= CAST(bt.Billabletime AS INT)
                                                OR
                                                bt.Billabletime = 900
                                            )
                                    THEN 1
                                    ELSE 0
                                 END
        ,dvce_type          = ftlc.dvce_type    
    FROM dbo.Abc       d WITH (NOLOCK)
    INNER JOIN dt.cde cd WITH (NOLOCK) ON d.FullDate = CAST(cd.CallDateTime AS DATE)
    INNER JOIN dt.hij  m WITH (NOLOCK) ON cd.CallerId = m.DialogTechPhoneNumber
    INNER JOIN dt.klm  bt WITH (NOLOCK) ON m.LeadSourceInfoId = bt.LeadSourceId
                                            AND cd.CallDateTime BETWEEN bt.StartDateTime AND ISNULL(bt.EndDateTime, GETDATE())
    INNER JOIN dbo.jkl ftlc WITH (NOLOCK) ON bt.ParentLeadSource = ftlc.fruit
    INNER JOIN dbo.xyz cpl WITH (NOLOCK) ON ftlc.lead_company = cpl.lead_company
                                             AND cd.CallDateTime BETWEEN cpl.start_date AND ISNULL(cpl.end_date, GETDATE())
    WHERE
        d.FullDate >= '2018-08-01'
        AND (
                ISNUMERIC(cd.TalkTimeMinutes) = 1 
                AND (
                        CAST(cd.TalkTimeMinutes AS DECIMAL(10, 2)) * 60 >= CAST(bt.Billabletime AS INT)
                        OR
                        bt.Billabletime = 900
                    )
            )
) sub
GROUP BY
    CallDate
    ,MediaChannel
    ,SubCategory
    ,Vendor
    ,BusinessVertical
    ,SourceName
    ,ParentLeadSource
    ,IsBillable
    ,dvce_type;
...