为什么我的新SQL视图/查询忽略了我的业务规则?

时间:2017-04-14 16:17:07

标签: sql function view sql-server-2008-r2

这是一个非常复杂的问题,我提前道歉。我一直在对我的问题进行大量的分析和研究,但我找不到任何答案。

如果这是相关的,我正在使用SQL Server 2008 R2。

我创建了一个根据我的业务规则工作的标量值函数,但在存储过程中使用时需要17分钟才能运行。这也是全部R.B.A.R.这让我很烦恼。

结果,我正在尝试编写一个视图来替换它。我编写并加入存储过程的视图需要7秒才能运行。问题在于它不遵守所有业务规则。

我会发布原始函数和新视图,但首先我会尝试先解释业务规则,因为这一切都很混乱。

  1. 如果销售完成,请返回“已完成”。

  2. 如果销售编号未完成,但另一位销售人员确实完成了销售,请返回“已保存”。

  3. 如果没有销售人员能够完成销售:

    一个。并且客户取消了销售,返回“已取消”

    湾只有一个销售人员试图进行销售,返回“错过”

    ℃。不止一个销售人员试图进行销售,但都错过了:

    我。如果其中一个销售人员“拥有”客户帐户,请将其电话号码“遗漏”,并将任何其他相关的电话号码“遗漏”

    II。如果没有销售人员拥有客户帐户,请将“错过”添加到首先收到订单的销售人员。

  4. 最后注意:每个客户订单/销售都有一个统一的“CallNumber”,其中包含一个或多个“SalesNumbers”的列表,这些列表都是销售人员尝试完成订单。

    这是函数

    ALTER FUNCTION [dbo].[FindMissedVsSaved]
    

    (     @SalesNumber int,     @SalesDate nvarchar(10) ) 返回nvarchar(20) 如 BEGIN

    DECLARE @Status AS nvarchar(20)
    
    DECLARE @Year AS int
    SET @Year = YEAR(@SalesDate)
    

    - 此部分用于确定客户的“所有者”是谁;它仅用于双重失误

    DECLARE @SalesPerson AS nvarchar(6)
    DECLARE @SalesType AS int
    SET @SalesType = (SELECT SalesType FROM MyDB.dbo.Calls WHERE SalesNumber=@SalesNumber AND SalesDate = @SalesDate)
    SET @SalesPerson =
        CASE 
            WHEN @SalesType IN (8, 12) THEN 
                ISNULL((SELECT TOP (1) b.SalesPersonName From MyDB.dbo.Calls AS t
                JOIN MyDB.dbo.Call_Sources AS cs ON t.callsource = cs.code
                JOIN AccountAssignment AS csa ON cs.code = csa.MyDBAccountAssignmentID
                JOIN SalesPerson AS b ON csa.AssignedSalesPersonID = b.SalesPersonID
                WHERE t.SalesDate = @SalesDate AND t.SalesNumber = @SalesNumber), 'No Assigned Sales Person')
            WHEN @SalesType IN (9, 10, 13, 14) THEN
                ISNULL((SELECT TOP (1) b.SalesPersonName From MyDB.dbo.Calls AS t
                JOIN MyDB.dbo.Customer AS f ON t.ofac = f.code
                JOIN SalesPerson AS b ON f.MyDBSales_Person = b.MyDBSales_Person
                WHERE t.SalesDate = @SalesDate AND t.SalesNumber = @SalesNumber), 'No Assigned Sales Person')
            ELSE 'Error'
        END
    DECLARE @MissedSalesPerson AS nvarchar(6)
    SET @MissedSalesPerson = 
        (SELECT TOP (1) ui.SalesPersonID FROM MyDB.dbo.Calls AS t
        JOIN MyDB.dbo.Vehicle_Schedule AS vs On t.SchRecNo = vs.schrecno
        JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
        WHERE t.SalesNumber=@SalesNumber AND t.SalesDate=@SalesDate)
    

    - 为这些记录拉出唯一的CallNumber

    DECLARE @CallNumber AS nvarchar(15)
    SET @CallNumber = (
        SELECT TOP (1) CallNumber 
        FROM MyDB.dbo.Calls 
        WHERE SalesNumber = @SalesNumber 
        AND SalesDate = @SalesDate)
    

    - 如果出售并且世界卫生组织进行了销售,则数字

    DECLARE @SavedSalesPerson AS nvarchar(8)
    SET @SavedSalesPerson = (SELECT TOP (1) ui.SalesPersonID
    --DISTINCT(ui.SalesPersonID )
                FROM MyDB.dbo.Calls AS t
                JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                WHERE YEAR(SalesDate) = @Year 
                AND CallNumber=@CallNumber 
                AND SalesNumber <> @SalesNumber
                AND SaleMade = 7
                AND SalesType IN (8, 9, 10, 12, 13, 14)) 
    

    - 此最后一节设置要为此特定SalesNumber

    返回的状态
    SET @Status = 
        CASE
            -- The Call Number passed in Made the sale
            WHEN EXISTS (SELECT TOP (1) SaleMade FROM MyDB.dbo.Calls
                WHERE YEAR(SalesDate) = @Year 
                AND CallNumber=@CallNumber 
                AND SalesNumber = @SalesNumber AND SaleMade = 7)
            THEN 'Completed'
    
            --The Call Number passed in did NOT make the sale but another sales person was able to accept the call but the customer cancelled
            WHEN EXISTS(SELECT TOP (1) CxlReason FROM MyDB.dbo.Calls
                WHERE YEAR(SalesDate) = @Year 
                AND CallNumber=@CallNumber 
                AND SalesNumber <> @SalesNumber 
                AND CxlReason IN (3, 6, 7, 8, 13, 27, 32, 33, 36, 37, 44, 46)
                AND SalesType IN (8, 9, 10, 12, 13, 14))
            THEN 'Cancelled' 
    
            --Another Sales Person made the sale  i.e. save
            WHEN EXISTS(
                SELECT TOP (1) ui.SalesPersonID 
                FROM MyDB.dbo.Calls AS t
                JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                WHERE YEAR(SalesDate) = @Year 
                AND CallNumber=@CallNumber 
                AND SalesNumber <> @SalesNumber
                AND SaleMade = 7
                AND SalesType IN (8, 9, 10, 12, 13, 14)) 
            THEN 'Saved by ' + @SavedSalesPerson
    
            --When it has a MISC15 timestamp on it, but doesn't meet the saved criteria
            WHEN 
                (SELECT TOP (1) tmt.Misc15 
                FROM MyDB.dbo.Calls AS t
                LEFT OUTER JOIN MyDB.dbo.Trip_Misc_Times AS tmt ON t.SalesDate = tmt.SalesDate AND t.job = tmt.job
                WHERE t.SalesNumber = @SalesNumber AND YEAR(t.SalesDate) = @Year) IS NOT NULL
            THEN 'Other'
    
            --The miss should always go on the Sales Person who Owns the Customer Account, if they attempted the Sale
            WHEN @MissedSalesPerson = @SalesPerson THEN 'Missed'
    
            --For cases when this was the only sales person that attempted to make the sale and s/he was unable to complete it
            WHEN NOT EXISTS(SELECT TOP (1) ui.SalesPersonID 
                FROM MyDB.dbo.Calls AS t
                JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                WHERE YEAR(SalesDate) = @Year 
                    AND CallNumber=@CallNumber 
                    AND SalesNumber <> @SalesNumber         
                    AND SalesType IN (8, 9, 10, 12, 13, 14)) 
            THEN 'Missed'
    
            --Looking for another SalesPerson that might have attempted the Sale
            WHEN @MissedSalesPerson <> @SalesPerson AND @SalesPerson <> 'No Assigned Sales Person' THEN
                CASE
                    --Another Sales Person attempted the transport and the Customer Cancelled
                    WHEN                    
                        EXISTS(SELECT TOP (1) SalesNumber 
                            FROM MyDB.dbo.Calls
                            WHERE SalesDate=@SalesDate AND CallNumber = @CallNumber
                            AND SalesNumber <> @SalesNumber
                            AND cxlReason IN (3, 6, 7, 8, 13, 27, 32, 33, 36, 37, 46)
                            AND SalesType IN (8, 9, 10, 12, 13, 14))
                    THEN 'Not Missed'
    
                    --Owner Sales Person also attempted and missed
                    WHEN                    
                        EXISTS(SELECT TOP (1) ui.SalesPersonID 
                            FROM MyDB.dbo.Calls AS t
                            JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                            JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                            WHERE YEAR(SalesDate) = @Year 
                                AND CallNumber=@CallNumber 
                                AND SalesNumber <> @SalesNumber
                                AND ui.SalesPersonID = @SalesPerson
                                AND SalesType IN (8, 9, 10, 12, 13, 14)) 
                    THEN 'Not Missed'
    
                    --Another Sales Person attempted the sale but the Sales Person for this Call was given the call first
                    WHEN EXISTS(SELECT TOP (1) ui.SalesPersonID 
                            FROM MyDB.dbo.Calls AS t
                            JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                            JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                            WHERE YEAR(SalesDate) = @Year 
                                AND CallNumber=@CallNumber 
                                AND SalesNumber <> @SalesNumber
                                AND ui.SalesPersonID <> @SalesPerson
                                AND SalesType IN (8, 9, 10, 12, 13, 14)) 
                        AND @MissedSalesPerson = 
                            (SELECT Top (1) ui.SalesPersonID 
                            FROM MyDB.dbo.Calls AS t
                            Join MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                            JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                            WHERE t.SalesDate = @SalesDate 
                            AND t.CallNumber = @CallNumber
                            AND t.SalesType IN (8, 9, 10, 12, 13, 14)
                            ORDER BY t.calltime)
                    THEN 'Missed'
    
                    --Another Sales Person attempted the sale and the Sales Person for this Call/Transaction was NOT called first
                    WHEN EXISTS(SELECT TOP (1) ui.SalesPersonID 
                            FROM MyDB.dbo.Calls AS t
                            JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                            JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                            WHERE YEAR(SalesDate) = @Year 
                                AND CallNumber=@CallNumber 
                                AND SalesNumber <> @SalesNumber
                                AND ui.SalesPersonID <> @SalesPerson
                                AND SalesType IN (8, 9, 10, 12, 13, 14)) 
                        AND @MissedSalesPerson <> 
                            (SELECT Top (1) ui.SalesPersonID 
                            FROM MyDB.dbo.Calls AS t
                            Join MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo = vs.schrecno
                            JOIN MyDB.dbo.SalesPeople AS ui ON vs.unit_code = ui.code
                            WHERE t.SalesDate = @SalesDate 
                            AND t.CallNumber = @CallNumber
                            AND t.SalesType IN (8, 9, 10, 12, 13, 14)
                            ORDER BY t.calltime)
                    THEN 'Not Missed'
    
                    --Anything that I missed
                    ELSE 'ERR'  
                END
    
        END
    
    RETURN @Status
    

    以下是我为了取代上面的混乱而写的观点:

    ---- Main Data
    
        WITH a AS (SELECT t.SalesDate, t.CallNumber, t.SalesNumber, cr.descr AS CancelReason, t.SaleMade, f.MyDBSales_Person AS OFacAcctOwner, b2.SalesPersonNumber AS CSAcctOwner, cr.code AS CancelCode, ui.SalesPersonID AS SalesPersonThatMissed, tmt.misc15, t.calldate + ' ' + t.calltime AS CallDate,  t.SalesType,
            AccountOwner = 
                CASE
                    WHEN t.SalesType IN (8, 12) THEN b.SalesPersonNumber
                WHEN t.SalesType IN (9, 10, 13, 14) AND LEN(f.MyDBSales_Person) < 2 THEN 'LF 0' + CAST(f.MyDBSales_Person AS nvarchar(1)) 
                WHEN t.SalesType IN (9, 10, 13, 14) AND LEN(f.MyDBSales_Person) >= 2 THEN 'LF ' + CAST(f.MyDBSales_Person AS nvarchar(2))
                END
            FROM  MyDB.dbo.Calls AS t 
            LEFT JOIN MyDB.dbo.Cancellation_Reasons AS cr ON t.CxlReason = cr.code
            LEFT JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo=vs.schrecno     
            LEFT JOIN MyDB.dbo.Customers AS f ON t.ofac = f.code
            LEFT JOIN MyDB.dbo.Call_Sources AS cs ON t.callsource = cs.code
            LEFT JOIN MyDB.dbo.SalesTypes AS p ON t.SalesType=p.code     
            LEFT JOIN MyDB.dbo.Trip_Misc_Times AS tmt ON t.job=tmt.job AND t.SalesDate=tmt.SalesDate     
            LEFT JOIN MyDB.dbo.SalesPerson_IDs AS ui ON vs.SalesPerson_code=ui.code    
            LEFT JOIN SalesPeople AS b On ui.SalesPersonID = b.SalesPersonNumber AND b.IsActive = 1
            LEFT JOIN AccountAssignment AS csa ON cs.code = csa.ZollCallSourceID
            LEFT JOIN SalesPeople AS b2 ON csa.AssignedSalesPersonID = b2.SalesPersonID
            WHERE t.SalesType IN (1, 2, 8, 9, 10, 12, 13, 14, 18) 
            AND t.SalesNumber>0 AND ui.SalesPersonID NOT LIKE 'LF 00%' AND ui.SalesPersonID NOT LIKE 'IAA%' ),
    
    ---- Checks Completed
    
    b AS 
        (
    
    SELECT t.CallNumber, t.SaleMade, t.SalesType, ui.SalesPersonID, t.SalesNumber, 
        t.calldate + ' ' + t.calltime AS CallDate 
        --CAST(t.calltime + ' ' + t.calldate AS datetime2(1)) AS CallDate 
        FROM MyDB.dbo.Calls AS t
        LEFT JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo=vs.schrecno     
        LEFT JOIN MyDB.dbo.SalesPerson_IDs AS ui ON vs.SalesPerson_code=ui.code    
        WHERE SalesType IN (8, 9, 10, 12, 13, 14) AND t.SaleMade=7
        AND t.SalesNumber>0 AND ui.SalesPersonID NOT LIKE 'LF 00%' AND ui.SalesPersonID NOT LIKE 'IAA%'),
    
    ---- Checks other Missed
    
    c AS
        (
    
    SELECT DISTINCT (c2.SalesNumber), c1.CallNumber, c2.SalesPersonID, c1.CallC1 AS CallDate--,  c2.CancelReason, c2.CancelCode 
        FROM
        (SELECT --TOP (1) --> top 1 retuns MORE rows, not less 
        MIN(t.calldate + ' ' + t.calltime) AS CallC1, t.CallNumber
        FROM MyDB.dbo.Calls AS t
        LEFT JOIN MyDB.dbo.Cancellation_Reasons AS cr ON t.CxlReason = cr.code
        LEFT JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo=vs.schrecno     
        LEFT JOIN MyDB.dbo.SalesPerson_IDs AS ui ON vs.SalesPerson_code=ui.code    
        WHERE SalesType IN (8, 9, 10, 12, 13, 14) AND t.SaleMade <> 7
        AND t.SalesNumber > 0 
        AND ui.SalesPersonID NOT LIKE 'LF 00%' 
        AND ui.SalesPersonID NOT LIKE 'IAA%'
        AND cr.code IN (14, 16, 17, 18, 19, 21, 22, 23, 24, 25, 30, 31, 38 , 40, 41, 42, 43, 45)
        GROUP BY t.CallNumber)
        AS c1
        JOIN 
        (SELECT t.CallNumber, t.SaleMade, t.SalesType, ui.SalesPersonID, t.SalesNumber, 
        t.calldate + ' ' + t.calltime AS CallDate, cr.descr AS CancelReason, cr.code AS CancelCode
        FROM MyDB.dbo.Calls AS t
        LEFT JOIN MyDB.dbo.Cancellation_Reasons AS cr ON t.CxlReason = cr.code
        LEFT JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo=vs.schrecno     
        LEFT JOIN MyDB.dbo.SalesPerson_IDs AS ui ON vs.SalesPerson_code=ui.code    
        WHERE SalesType IN (8, 9, 10, 12, 13, 14) AND t.SaleMade <> 7
        AND t.SalesNumber>0 AND ui.SalesPersonID NOT LIKE 'LF 00%' AND ui.SalesPersonID NOT LIKE 'IAA%'
        AND cr.code IN (14, 16, 17, 18, 19, 21, 22, 23, 24, 25, 30, 31, 38 , 40, 41, 42, 43, 45)
        ) 
        AS c2
        ON c1.CallNumber = c2.CallNumber AND c1.CallC1 = c2.CallDate),
    
    ----Checks Cancelled
    
    d AS 
        (
    
    SELECT  t.CallNumber, t.SaleMade, t.SalesType, ui.SalesPersonID, t.SalesNumber, 
        t.calldate + ' ' + t.calltime AS CallDate, cr.descr AS CancelReason, cr.code AS CancelCode
        FROM MyDB.dbo.Calls AS t
        LEFT JOIN MyDB.dbo.Cancellation_Reasons AS cr ON t.CxlReason = cr.code
        LEFT JOIN MyDB.dbo.Vehicle_Schedule AS vs ON t.SchRecNo=vs.schrecno     
        LEFT JOIN MyDB.dbo.SalesPerson_IDs AS ui ON vs.SalesPerson_code=ui.code    
        WHERE SalesType IN (8, 9, 10, 12, 13, 14) AND t.SaleMade <> 7
        AND t.SalesNumber>0 AND ui.SalesPersonID NOT LIKE 'LF 00%' AND ui.SalesPersonID NOT LIKE 'IAA%' 
        AND cr.code IN (3, 6, 7, 8, 13, 27, 32, 33, 36, 37, 46))
    
    
    
    SELECT DISTINCT(a.SalesDate), a.SalesNumber, a.accountowner,
        TransportStatus = 
            CASE
                WHEN a.SaleMade = 7 THEN 'Completed'
                WHEN a.CancelReason = '<NONE>' THEN 'Completed'
                WHEN a.CancelCode IN (3, 6, 7, 8, 13, 27, 32, 33, 36, 37, 46) 
                    THEN 'Cancelled'
                WHEN a.CancelCode IN (-1, 1, 2, 4, 5, 9, 10, 11, 12, 15, 20, 26, 28, 29, 34, 35, 39, 44) 
                    THEN 'Ignore'
                WHEN b.SalesNumber IS NOT NULL 
                    AND a.SalesType IN (8, 9, 10, 12, 13, 14) THEN 'Saved by ' + b.SalesPersonID
                WHEN a.misc15 IS NOT NULL THEN 'Not Missed'
                WHEN a.SalesType IN (1, 2, 18) AND (a.SaleMade <> 7 OR a.CancelReason <> '<None>')
                    THEN '(Missed) ' + a.CancelReason
                WHEN d.SalesNumber IS NOT NULL THEN 'Not Missed'
                WHEN c.SalesNumber <> a.SalesNumber AND c.SalesPersonID = a.AccountOwner THEN 'Not Missed'
                WHEN c.SalesNumber <> a.SalesNumber AND a.SalesPersonThatMissed <> a.AccountOwner  THEN 'Not Missed'    
                WHEN a.SalesPersonThatMissed = a.AccountOwner THEN '(Missed) ' + a.CancelReason
                WHEN c.SalesNumber = a.SalesNumber THEN '(Missed) ' + a.CancelReason
                WHEN c.SalesNumber IS NULL AND b.SalesNumber IS NULL AND d.SalesNumber IS NULL 
                    THEN '(Missed) ' + a.CancelReason
                ELSE  'Err' 
            END
    
    FROM 
        a
        LEFT OUTER JOIN 
        b ON a.CallNumber = b.CallNumber
        LEFT OUTER JOIN 
        c ON a.CallNumber = c.CallNumber 
        LEFT OUTER JOIN 
        d ON a.CallNumber = d.CallNumber
    
        WHERE SalesDate >= '2012-01-01'
    

1 个答案:

答案 0 :(得分:0)

我终于明白了。

我没有考虑问题的所有可能的排列,因此,视图并没有按照应有的方式处理业务规则。

我最后添加了另一个CTE(虽然,我并不完全确定这些计算为CTE)以及最后的Case语句的进一步逻辑。