2017-08-26 337 views
2

我想通過添加一個2周容差片來調整下面的代碼。與最小最大公差

它做什麼它看起來當第一次客戶(標識符)創建一個請求,並在第一次完成並計算之間發生的日子。

但是我試圖添加一個公差片。其中說明了在這些日期之間發生的NCO數量,以及如果在完成日期的2周內發生的完成日期之後還有進一步的請求,那麼也計算這些(同一請求的一部分)。完成日期的兩週之後的任何事情都視爲新請求。

CREATE TABLE #temp 
(
Identifier varchar(40)NOT NULL 
,Created_Date DATETIME NOT NULL 
,Completed_Date DATETIME NULL 
,SN_Type varchar(20) NOT NULL 
,SN_Status varchar(20) NOT NULL 
) 
; 

INSERT INTO #temp 
VALUES ('3333333','2017-02-14 15:00:40.000','2017-02-15 00:00:00.000','Re-Activattion', 'COMP'); 
INSERT INTO #temp 
VALUES ('3333333','2017-05-24 16:41:04.000','2017-06-05 00:00:00.000','Re-Activattion', 'N-CO'); 
INSERT INTO #temp 
VALUES ('3333333','2017-05-25 11:49:54.000','2017-05-26 00:00:00.000','Re-Activattion', 'COMP'); 
INSERT INTO #temp 
VALUES ('3333333','2017-06-27 10:24:29.000',NULL,'Re-Activattion', 'ACC'); 

@Alex你的代碼是準確的只是我想可以選擇記錄創建第二次最小日期,所以結果的第2行應返回分鐘日期爲2017年5月24日16: 41:04.000。

select identifier 
     ,case 
      when sum(case when SN_STATUS='COMP' and SN_TYPE = 'Re-Activattion' then 1 else 0 end)>0 
      then str(datediff(day 
          ,MIN(case 
            when SN_TYPE = 'Re-Activattion' 
            then Created_Date 
            else null 
           end 
           ) 
          ,min(case 
            when (SN_TYPE = 'Re-Activattion' 
            and SN_STATUS='COMP' 
             ) 
            then Completed_Date 
            else null 
           end 
           ) 
          ) 
       ) 
      when sum(case when SN_TYPE='Re-Activattion' then 1 else 0 end)>0 
      then 'NOT COMP' 
      else 'NO RE-ACT' 
     end 
     as RE_ACT_COMPLETION_TIME 
     ,Sum(CASE WHEN SN_STATUS = 'N-CO' THEN 1 ELSE 0 END) as [RE-AN NCO #] 
    from #temp 
group by identifier 
; 

結果我終究:因爲是特定的順序啓動和訂單的結束沒有明確的記錄

enter image description here

+0

可以提供其中NCO不計的樣本數據? –

回答

1

你的表的設計是不是最佳的,這些類型的查詢。此外,多個訂單以相同的標識符存儲。

要解決此問題,您需要自行計算/識別訂單開始和訂單結束記錄。

一種方法是使用Common Table Expressions

注意:我已經添加了註釋以解釋每個部分的功能。

-- calculate/identify Order start and Order End records 
WITH cte AS 
(
    -- 1st Order start record i.e. earliest record in the table for a given "Identifier" 
    SELECT Identifier, MIN(Created_Date) AS Created_Date, CONVERT(VARCHAR(30), 'Created') AS RecordType, 1 AS OrderNumber 
    FROM #temp 
    GROUP BY Identifier 
    UNION ALL 
    -- All records with "COMP" status are treated as order completed events. Add 2 weeks to the completed date to create a "dummy" Order End Date 
    SELECT Identifier, DATEADD(WEEK, 2, Created_Date) AS Created_Date, 'Completed' AS RecordType, ROW_NUMBER() OVER(PARTITION BY Identifier ORDER BY Created_Date) AS OrderNumber 
    FROM #temp 
    WHERE SN_STATUS = 'COMP' 
    UNION ALL 
    -- Set the start period of the next order to be right after (3 ms) the previous Order End Date 
    SELECT Identifier, DATEADD(ms, 3, DATEADD(WEEK, 2, Created_Date)) AS Created_Date, 'Created' AS RecordType, ROW_NUMBER() OVER(PARTITION BY Identifier ORDER BY Created_Date) + 1 AS OrderNumber 
    FROM #temp 
    WHERE SN_STATUS = 'COMP' 
), 
-- Combine Start/End records into one record 
OrderGroups AS(
    SELECT Identifier, OrderNumber, MIN(Created_Date) AS OrderRangeStartDate, MAX(Created_Date) AS OrderRangeEndDate 
    FROM cte 
    GROUP BY Identifier, OrderNumber 
) 

SELECT a.Identifier, a.OrderNumber, OrderRangeStartDate, OrderRangeEndDate, 
    case 
      when sum(case when SN_STATUS='COMP' and SN_TYPE = 'Re-Activattion' then 1 else 0 end)>0 
      then str(datediff(day 
          ,MIN(case 
            when SN_TYPE = 'Re-Activattion' 
            then Created_Date 
            else null 
           end 
           ) 
          ,min(case 
            when (SN_TYPE = 'Re-Activattion' 
            and SN_STATUS='COMP' 
             ) 
            then Completed_Date 
            else null 
           end 
           ) 
          ) 
       ) 
      when sum(case when SN_TYPE='Re-Activattion' then 1 else 0 end)>0 
      then 'NOT COMP' 
      else 'NO RE-ACT' 
     end as RE_ACT_COMPLETION_TIME, 
    Sum(CASE WHEN SN_STATUS = 'N-CO' THEN 1 ELSE 0 END) as [RE-AN NCO #] 
FROM OrderGroups AS a 
    INNER JOIN #Temp AS b ON a.Identifier = b.Identifier AND a.OrderRangeStartDate <= b.Created_Date AND b.Created_Date <= a.OrderRangeEndDate 
GROUP BY a.Identifier, a.OrderNumber, OrderRangeStartDate, OrderRangeEndDate 

輸出:

Identifier  OrderNumber OrderRangeStartDate  OrderRangeEndDate  RE_ACT_COMPLETION_TIME RE-AN NCO # 
-------------- ------------- ----------------------- ----------------------- ---------------------- ----------- 
200895691  1    2016-01-27 14:25:00.000 2016-02-10 15:15:00.000   0    2 
200895691  2    2016-02-10 15:15:00.003 2017-01-16 12:15:00.000   1    1 

輸出,用於更新的數據集:

Identifier OrderNumber OrderRangeStartDate  OrderRangeEndDate  RE_ACT_COMPLETION_TIME RE-AN NCO # 
------------ ------------ ----------------------- ----------------------- ---------------------- ----------- 
200895691 1   2017-01-11 00:00:00.000 2017-03-27 00:00:00.000   61    4 
200895691 2   2017-03-27 00:00:00.003 2017-04-20 00:00:00.000   1    1 
3333333  1   2017-01-27 00:00:00.000 2017-02-10 00:00:00.000   0    2 
44454544  1   2017-01-27 00:00:00.000 2017-01-27 00:00:00.000 NOT COMP    1 
7777691  1   2017-02-08 09:36:44.000 2017-02-22 09:36:44.000   63    1 

更新2017年10月5日在迴應評論

輸入:

INSERT INTO #temp VALUES 
('11111','20170203','20170203','Re-Activattion', 'COMP'), 
('11111','20170206','20170202','Re-Activattion', 'N-CO'); 

輸出:

Identifier OrderNumber OrderRangeStartDate  OrderRangeEndDate  RE_ACT_COMPLETION_TIME RE-AN NCO # 
---------- ------------ ----------------------- ----------------------- ---------------------- ----------- 
11111  1   2017-02-03 00:00:00.000 2017-02-17 00:00:00.000   0    1 
+1

嗨,亞歷克斯。感謝您放棄這一切。我知道理想的數據,並且很難處理。我嘗試了你的代碼,儘管在我提供的例子中它很好用,我在幾個場景中嘗試過(見上面更新的數據集),但並沒有安靜地融合在一起。我厭倦了使用羣島。非常接近,但仍然沒有蛋糕。 – Danielle

+0

@Danielle - 看起來我在查詢中犯了一個小錯誤,我忘了在INNER JOIN條件中包含Identifier(最後的'SELECT')。一旦我添加了這個條件,它就會返回「預期結果」(更新的結果)。讓我懷疑人們是否真的試圖理解解決方案.....無論如何,我已經更新了我的答案。 – Alex

+0

謝謝,像魅力一樣工作。只是我想添加的一件事是否第一次創建**,如果它是在同一天或第二天完成的。--- \t,CASE WHEN datediff(day,Created_Date,Completed_Date)= 0 THEN'SAME DAY'ELSE'NOT SAME DAY'end AS SANE_DAY_FLAG \t,CASE WHEN datediff(day,Created_Date,Completed_Date)= 1 THEN'NEXT DAY 'ELSE'NOT NEXT DAY'end AS NEXT_DAY_FLAG -----唯一的事情是我不在哪個島上彈出它。似乎無法得到正確的結果 – Danielle