2017-04-14 91 views
1

這是一個非常複雜的問題,對此我很抱歉。我一直在對我的問題進行大量的分析和研究,但我找不到任何答案。爲什麼我的新SQL查看/查詢忽略了我的業務規則?

如果這是相關的,我使用的是SQL Server 2008 R2。

我創建了根據我的業務規則工作的標值的功能,但在存儲過程中使用時,需要17分鐘來運行。此外,這全是R.B.A.R.這只是令我煩惱。

因此,我試圖寫一個視圖來取代它。我寫入並加入到存儲過程的視圖需要7秒鐘才能運行。問題是它不遵守所有的業務規則。

我會後雙方原有的功能,再加上新的觀點,但首先我要去嘗試前手講解業務規則,因爲這整件事是凌亂。

  1. 如果銷售完成,則返回「已完成」。

  2. 如果銷售數量沒有完成,但另一銷售人員做了完整的銷售,返回「保存」。

  3. 如果沒有銷售人員能夠完成銷售:

    一個。並且客戶取消了銷售,返回「取消」

    b。只有一個銷售人員試圖進行銷售,返回「錯過」

    ℃。不止一個銷售員試圖進行銷售,但都錯過:

    我。如果這些銷售人員「擁有」客戶賬戶的一個,讓自己的電話號碼「遺漏」及其他相關呼叫號碼「不會錯過」

    II。如果沒有任何銷售人員擁有客戶帳戶,請將「錯過」添加到首先收到訂單的銷售人員。

末注:每個客戶訂單/銷售有一個統一的「CallNumber」,與一個或多個「SalesNumbers」,這是每一個銷售人員試圖完成訂單列表。

這裏的功能

ALTER FUNCTION [dbo].[FindMissedVsSaved] 

( @SalesNumber INT, @SalesDate爲nvarchar(10) ) RETURNS爲nvarchar(20) AS 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 [email protected] 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 [email protected] AND [email protected]) 

- 拉這些記錄

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

--Figures出當銷售的製成,誰做銷售獨特CallNumber

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 [email protected] 
      AND SalesNumber <> @SalesNumber 
      AND SaleMade = 7 
      AND SalesType IN (8, 9, 10, 12, 13, 14)) 

- 此最終部分設置要爲此特定銷售編號返回的狀態

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 [email protected] 
      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 [email protected] 
      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 [email protected] 
      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 [email protected] 
       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 [email protected] 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 [email protected] 
          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 [email protected] 
          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 [email protected] 
          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' 

回答

0

我終於想通了。

我沒有考慮過這個問題的所有可能的排列,因此,這個視圖並沒有處理它應該有的業務規則。

我最終添加了另一個CTE(儘管我不完全確定這些算作CTE),並且最終還是對Case語句進行了進一步的邏輯。