SQL Server计算总时间低于阈值

时间:2017-04-04 22:37:02

标签: sql sql-server

也许有人可以帮助我。我一直在尝试创建一个查询,总结项目低于阈值的时间。我的数据如下:

enter image description here

我试图找到NR列与阈值5 相差不等的最新日期。我的数据最好在下面的图表中可视化: enter image description here

对于A的情况,最后一个点高于5,所以这不会给出值。 B在2/8/2017等于或低于阈值,C从不高于。在这种情况下,我会使用第一个系列事件(带圆圈)。

我创建的代码几乎得到了答案。请注意,我在代码中有一个最后一步,计算从低于阈值的点到低于阈值的最后一点的几周内的数据差异。例如在B中 - 这将是2/8/2017和2017年2月28日之间的差异。

代码是:

    IF OBJECT_ID('tempdb.dbo.#TAB', 'U') IS NOT NULL
  DROP TABLE #TAB; 

  CREATE TABLE #TAB (SL VARCHAR(5), NR FLOAT, Date Date)
INSERT INTO #TAB VALUES
('A',   '10',   '1/1/2017'),
('A',   '4',    '1/15/2017'),
('A',   '12',   '2/1/2017'),
('A',   '4',    '2/7/2017'),
('A',   '3',    '2/15/2017'),
('A',   '6',    '2/28/2017'),
('B',   '10',   '1/1/2017'),
('B',   '8' ,'1/15/2017'),
('B',   '7' ,'2/1/2017'),
('B',   '5',    '2/7/2017'),
('B',   '4',    '2/15/2017'),
('B',   '4' ,'2/28/2017'),
('C',   '4',    '1/1/2017'),
('C',   '4',    '1/15/2017'),
('C',   '3' ,'2/1/2017'),
('C',   '3',    '2/7/2017'),
('C',   '3' ,'2/15/2017'),
('C'    ,'2',   '2/28/2017')





;WITH CTE1 AS(

  SELECT *, ROW_NUMBER() OVER (PARTITION BY SL ORDER BY Date) Rn_ix  FROM [#TAB])
 ,
CTE2 AS 

(
SELECT 
CTE1.SL,
NR,
CTE1.Date Max_Date
FROM CTE1 INNER JOIN (SELECT MAX(Date) Date, SL FROM CTE1 GROUP BY SL) NEW ON CTE1.Date = NEW.Date AND CTE1.SL = NEW.SL 
)
, 
CTE3 AS 
(
  SELECT 
  CTe1.SL,
  MIN(Date) Sample_date_Max,
  MAX(Rn_IX) as Max_Row_Number,
  CTE2.Max_Date
  FROM CTE1 INNER JOIN CTE2 ON CTE1.SL = CTE2.SL 
  WHERE CTE1.NR <= 5
  GROUP BY CTE1.SL, CTE2.Max_Date
 )
 , 
 CTE4 AS
 (
 SELECT SL, MAX(Date) as SampleDate, MAX(Rn_ix) Rn_IX 
 FROM CTE1 WHERE NR >5  GROUP BY SL

 ),


  CTE5 AS
  (SELECT CTE1.SL, CTe1.Date, NR 
  FROM CTE4 
  INNER JOIN CTE1 ON CTE4.Rn_IX = CTE1.Rn_ix-1

  and CTE4.SL = CTe1.SL )

  SELECT 
  CTe2.SL,
  DATEDIFF(WEEK, CTE5.Date, CTE2.Max_Date) as Weeks_Under,
ISNULL(CTE5.NR, CTE2.NR) AS NumericResult

  FROM CTE5 FULL OUTER JOIN CTE2 ON CTE2.SL = CTE5.SL
  ORDER BY CTE2.SL

这给了我以下结果:

enter image description here

B是正确的 - 它已经低于5,持续3周,并且在它超过之后的第一个结果值是5。 A是正确的 - 没有低于5的当前值。它下降但低于上面。数字结果是最新值 C不正确 - C总是低于5,我希望在数字结果中看到该系列的第一个值(01/01/2017,在这种情况下为4),在类别中的周数为8周。

简而言之,我希望最近的时间段低于或等于5以及相应的数字结果。

输出应如下所示:

enter image description here

我真的很感激任何帮助。如果这个问题措辞不当,请提前道歉。

提前致谢!

1 个答案:

答案 0 :(得分:1)

所以,如果我理解查询逻辑......

WeeksUnder是开始日期和结束日期之间的差异,如果它从未超过阈值,或者如果它超过阈值,则是上一个日期和结束日期之间的周差。

NumericResult是最新的NR,如果它当前高于阈值或者从未超过阈值,或者是第一个NR,它低于阈值。

在这种情况下,只需将此逻辑构建到这样的查询中:

SELECT SL,
       WeeksUnder = MAX(CASE WHEN LastDateAbove IS NULL THEN DATEDIFF(DAY, FirstDate, LastDate) / 7 WHEN LastDateAbove != LastDate THEN DATEDIFF(DAY, LastDateAbove, LastDate) / 7 END),
       NumericResult = MAX(CASE WHEN [Date] = COALESCE(LastDateAbove, LastDate) THEN COALESCE(NextNR, NR) END)
FROM
(
    SELECT T.SL,
           T.NR,
           T.[Date],
           C.LastDateAbove,
           C.FirstDate,
           C.LastDate,
           NextNR = (SELECT TOP 1 NR FROM #TAB WHERE SL = T.SL AND [Date] > C.LastDateAbove ORDER BY [Date])
    FROM #TAB T
    CROSS APPLY
    (
        SELECT LastDateAbove = MAX(CASE WHEN NR > 5 THEN [Date] END),
               FirstDate = MIN([Date]),
               LastDate = MAX([Date])
        FROM #TAB
        WHERE SL = T.SL
    ) AS C
) AS T
GROUP BY SL;