我的递归查询可以更快吗?

时间:2018-01-03 12:23:19

标签: sql sql-server recursive-query

我编写了下面的递归查询,从叶子或初始引导开始并返回所有先前的潜在客户,从而将一系列潜在客户带回来。

最终结果将被输入另一个查询,每个链产生一行,我一般不热衷于递归查询,但我没有看到另一种方法来写这个。

WITH [D1] AS
(
    SELECT 
        [Opp]._Customer_ID [CusID], 
        [Opp].Opportunity_ID [OppID], 
        [Opp].Reference [Ref], 
        [Opp].CoverStartDate_Actual [CoverStart], 
        [Opp].Date_Cancelled [Cancelled], 
        [Opp].Renewal, 
        [Opp]._Product_ID [ProID], 
        [Opp].inf_Opportunity_ID_Prior [PriorOppID], 
        [Opp].Policy_Number [PolicyNo], 
        [Opp].RealOpp [Real], 
        [Opp].Deleted, 
        [Opp].[Status],
        [Prior].Reference as PriorRef, 
        DATEDIFF(MONTH,[Prior].CoverStartDate_Actual,[Opp].CoverStartDate_Actual) as PriorOppMonthsApart, 
        [Prior].Months_Cover as PriorMonthsCover
    FROM 
        dbo.crm_Opportunity [Opp]
            LEFT OUTER JOIN dbo.crm_Opportunity [Prior] ON [Prior].Opportunity_ID = [Opp].inf_Opportunity_ID_Prior
    WHERE 
        ([Opp].Deleted = 0) 
        AND ([Opp].[Status] = 5) 
        AND ([Opp].RealOpp = 1)
),

这是返回我们将对其执行操作的所有数据的初始查询。我可以在这里添加一个TempTable或Table Varible来保存这个信息。

[D2] AS
(
    SELECT 
            [D1].OppID, 
            [D1].Ref, 
            [D1].CoverStart, 
            [D1].Cancelled, 
            [D1].Renewal, 
            [D1].ProID, 
            [D1].PriorOppID, 
            [D1].PolicyNo,
            1 AS Depth, 
            [D1].Ref AS TopRef, 
            CONVERT(VARCHAR(7),NULL) AS NextRef, 
            [D1].PriorRef, 
            [D1].PriorOppMonthsApart, 
            [D1].PriorMonthsCover, 
            [Cu].Introducer_Company_ID [Introducer], 
            [D1].OppID AS _Opportunity_ID_Top

    FROM 
            [D1] 
                INNER JOIN dbo.crm_Customer [Cu] ON [D1].CusID = [Cu].Customer_ID

    WHERE 
            ([Cu].Deleted = 0) 
            AND ([Cu]._Company_ID = 'bd164825-a16a-4bee-9b01-6971604dda63')
            AND 
                (
                SELECT 
                    COUNT(*) 
                FROM 
                    ACTIVEQUOTE.dbo.crm_Opportunity op2 
                WHERE 
                    ([D1].[PriorOppID] = [D1].OppID)
                    AND ([D1].Deleted = 0) 
                    AND ([D1].[Status] IN (2,3,4,5))
                ) = 0

    UNION ALL

    SELECT 
            [D1].OppID, 
            [D1].[Ref], 
            [D1].[CoverStart],
            [D1].[Cancelled], 
            [D1].Renewal, 
            [D1].[ProID], 
            [D1].PriorOppID, 
            [D1].PolicyNo,
            [D2].Depth + 1 as Depth, 
            [D2].TopRef, 
            CONVERT(VARCHAR(7),[D2].Ref) as NextRef, 
            [D1].PriorRef, 
            [D1].PriorOppMonthsApart, 
            [D1].PriorMonthsCover, 
            [D2].[Introducer], 
            [D2]._Opportunity_ID_Top

    FROM 
        [D1] 
            INNER JOIN [D2] ON [D1].OppID = [D2].PriorOppID
),

欢迎来到递归地狱,因为我说我不是递归查询的粉丝,但这是我可以使用的唯一方式来反馈链。该查询采用先前的引导引用并将其返回,直到它具有NULL先前引导的引导。

[D3] AS
(
SELECT  
        [D2].[ProID], 
        COUNT(*) OVER (PARTITION BY TopRef) AS Years, 
        [D2].Depth,
        [D2].TopRef, 
        [D2].Ref, 
        [D2].NextRef, 
        [D2].PriorRef, 
        CASE WHEN [D2].[PriorRef] IS NULL THEN 1 ELSE 0 END AS OriginOpp,
        [D2].Renewal,
        [D2].OppID,  
        [D2].CoverStart, 
        [D2].Cancelled,  
        [D2].PolicyNo, 
        [D2].PriorOppMonthsApart, 
        [D2].PriorMonthsCover,
        [D2].Introducer,
        [D2]._Opportunity_ID_Top
FROM 
        [D2]
)

SELECT 
    *
FROM 
    [D3]

最后一个难题是将数据格式化为可用行,PARTITION用于确定销售的年龄。

然后我选择一切。

1 个答案:

答案 0 :(得分:0)

您对Count = 0的内部查询不相关。当符合D1标准时,您计算机会中的所有行。

  WHERE 
            ...
            AND 
                (
                SELECT 
                    COUNT(*) 
                FROM 
                    ACTIVEQUOTE.dbo.crm_Opportunity op2 
                WHERE 
                    ([D1].[PriorOppID] = [D1].OppID)
                    AND ([D1].Deleted = 0) 
                    AND ([D1].[Status] IN (2,3,4,5))
                    --Should there be a relationship between op2 and D1?
                ) = 0

机会与D1有关系吗?否则,您可以通过将商机计数放入变量来加快速度。