简体   繁体   English

SQL子查询的运行速度非常快,但是在select中使用时非常慢

[英]SQL Sub-query run's very fast individually, but when used in select is very slow

I have a set of tables which i am joining to create a record set and then run a additional select on the set to retrieve some records. 我有一组表,我将这些表加入以创建记录集,然后在该集上运行其他选择以检索一些记录。 The query in the code is being used in a view as a CTE. 代码中的查询在视图中用作CTE。

While checking the sub-query only it runs extremely faster like 0.01 - 0.02 secs. 仅检查子查询时,它的运行速度非常快,如0.01-0.02秒。 same applies for if a temp table is used to retrieve the records. 如果使用临时表检索记录,则同样适用。 As I am planning to use it inside a view the temp table solution is Out of scope. 当我计划在视图中使用它时,临时表解决方案超出了范围。 The regular query runs from 37-50 mins instead. 常规查询的运行时间为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;

----The query is being used in view so need to tackle the sub query issue and reduce the running time. ----在视图中使用了查询,因此需要解决子查询问题并减少运行时间。

You have some data in your subquery that is not used in your outer query. 您的子查询中有一些未在外部查询中使用的数据。 Some of your joins could also introduce joining NULL values to NULL values, which will kill your performance. 您的某些联接还可能将NULL值联接到NULL值,这会降低性能。

Without knowing your table structures or functions, nor any of the actual data, I came up with the following simplified version of your query. 在不知道您的表结构或函数或任何实际数据的情况下,我想出了以下简化的查询版本。 It removes unused columns from the subquery, a subsequently-useless join, simplified CASE statements, and the removal of CostPerLead from the main query, since you're aggregating this. 它会从子查询中删除未使用的列,随后无用的CostPerLead ,简化的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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM