2012-12-13 43 views
1

我有关于SQL Server 2005的(TSQL)取决于状态的两个日期之间的分钟数

一个问题,我有两列 日期 状态

和数据看上去..像

Date     Status 

2012-09-01 00:01:00.000 2 

2012-09-01 04:17:00.000 4 

2012-09-01 04:34:00.000 4 

2012-09-01 04:35:00.000 4 

2012-09-01 04:35:48.000 4 

2012-09-01 04:35:51.000 1 

2012-09-01 17:28:25.000 2 

2012-09-01 23:58:00.000 4 

2012-09-01 23:59:00.000 1 

我需要计算状态之间的时间差...例如。最短的时间是当 状态2开始和最大时间当状态= 1(停止)之间我想要的分钟数。 我已经通过光标检查了状态并记录了变量的最小时间和最大时间。

我们是否可以使用CTE轻松完成这项工作。

我的问题需要很长时间才能完成......请帮助。

DECLARE @pdunitid INT 
     DECLARE @Date DATETIME 
     DECLARE @pddatetime DATETIME 
     DECLARE @pdstatus INT 
     DECLARE @starttime DATETIME 
     DECLARE @endTime DATETIME 
     DECLARE @calc INT 
     DECLARE @Totaltime INT 
     DECLARE @START INT 


     SET @pdunitid = 33568906 
     SET @Date = GETDATE() - 102 
     set @Totaltime = 0 
     SET @calc = 0 
     SET @START = 0 


     DECLARE s CURSOR FAST_FORWARD FOR 
     SELECT pddatetime,pdstatus FROM s1 WITH (NOLOCK) 
     WHERE pdunitid = @pdUnitid 
     AND CONVERT(VARCHAR,pddatetime,112) = CONVERT(VARCHAR,@Date,112) 
     ORDER BY pddatetime,pdstatus 

     OPEN s 

     FETCH NEXT FROM s INTO @pddatetime,@pdstatus 
     WHILE @@FETCH_STATUS = 0 
      BEGIN 
       -- status 2 is for start sometimes you don't get start so you will have to use the first date with status 4 

       IF pdstatus IN (2,4) AND @START = 0 
        BEGIN 
         SET @starttime = @pddatetime 
         SET @START = 1 
        END 

       -- status 1 is for stop 

       IF (@pdstatus= 1) 
        BEGIN 
         SET @endTime = @pddatetime 
         SET @calc = 1 
        END 

       -- if you dont get the status 1 by '23:59:00' take the end time 


      IF convert(varchar,@pdgpsdatetime,108) = '23:59:00' 
        BEGIN 
         SET @endTime = @pddatetime 
         SET @calc = 1 
      END 

       -- Calculate the minutes. 

       IF @calc = 1 
        BEGIN 
         SET @Totaltime = @Totaltime + DATEDIFF(mi, @starttime,@endTime) 
         SET @calc = 0 
         SET @START = 0 
        END 
     FETCH NEXT FROM s INTO @pddatetime,@pdstatus 
      END 
     CLOSE s 
     DEALLOCATE s 

     SELECT @Totaltime 
+0

请添加您的查询,你已经写了。 –

+0

你使用的是光标吗?这些效率不高。列索引?发布您尝试的TSQL。 –

+0

我已张贴由查询也...并评论哪里有它需要.. – user978324

回答

1

试试这个,而不是#tbl把你的表名:

DROP TABLE #tbl 
CREATE TABLE #tbl([Date] DATETIME, [Status] INT) 
INSERT #tbl 
VALUES 
('2012-09-01 00:01:00.000', 2), 
('2012-09-01 04:17:00.000', 4), 
('2012-09-01 04:34:00.000', 4), 
('2012-09-01 04:35:00.000', 4), 
('2012-09-01 04:35:48.000', 4), 
('2012-09-01 04:35:51.000', 1), 
('2012-09-01 17:28:25.000', 2), 
('2012-09-01 23:58:00.000', 4), 
('2012-09-01 23:59:00.000', 1), 

-- for 2012-09-05 there are no statuses 1 or 2 
--('2012-09-05 00:01:00.000', 2), 
('2012-09-05 04:17:00.000', 4), 
('2012-09-05 04:34:00.000', 4), 
('2012-09-05 04:35:00.000', 4), 
('2012-09-05 04:35:48.000', 4), 
('2012-09-05 04:35:51.000', 4), 
('2012-09-05 17:28:25.000', 4), 
('2012-09-05 23:58:00.000', 4) 
--('2012-09-05 23:59:00.000', 1) 

;WITH tbl AS 
(
    SELECT *, 
      ROW_NUMBER() OVER (ORDER BY [Date]) id 
    FROM #tbl 
), 
b AS 
(
    SELECT MIN([Date]) MinDate, 
      MAX([Date]) MaxDate, 
      CAST([Date] AS DATE) dateWithoutTime 
    FROM tbl 
    GROUP BY CAST([Date] AS DATE) 
), 
a AS 
(
    SELECT *, 
      ROW_NUMBER() OVER (ORDER BY [Date]) num 
    FROM tbl 
    LEFT JOIN 
      b ON 
      b.MaxDate = [Date] 
    OR  b.MinDate = [Date] 
    WHERE [Status] IN (2, 1) 
    OR  [Date] = CASE WHEN NOT EXISTS (SELECT 1 FROM #tbl c WHERE c.Status = 2 AND CAST(c.[Date] AS DATE) = b.dateWithoutTime) THEN b.MinDate END 
    OR  [Date] = CASE WHEN NOT EXISTS (SELECT 1 FROM #tbl c WHERE c.Status = 1 AND CAST(c.[Date] AS DATE) = b.dateWithoutTime) THEN b.MaxDate END 
) 

SELECT 
     tbl.Date, 
     tbl.Status, 
     CASE WHEN a2.num % 2 = 0 THEN DATEDIFF(MINUTE, a1.Date, a2.Date) END Diff 
FROM tbl 
LEFT JOIN 
     a a2 ON tbl.id = a2.id 
LEFT JOIN 
     a a1 ON a2.num = a1.num + 1 
ORDER BY [Date] 
+0

不客气,我希望它会帮助... –

+0

谢谢男人你很快..稍微改变了数据有时你不会获得状态2('2012-09-01 00:01:00.000',4),并且当天结束时将为('2012-09-01 23:59:00.000',4)他们开始将是第一个记录和结束将是最后一个记录,在你之间也可能有2和1 ..你能帮助..请 – user978324

+0

嗨伊万,我已评论你的查询,你可以看看和任何想法这请.. – user978324

相关问题