2017-08-26 155 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