Reputation: 59
I have a question related to Sql Server 2005 ( Tsql)
I have two columns Date Status
And the Data looks.. like
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
I need to calculate the time difference between the status ... for example. for min time is when status 2 start and max time when status= 1 (stop) between that date i want the number of minutes. I have done through the cursors checking the status and recording the minumum time and maximum time in the variables
Do we have any easy of doing it using CTE.
MY QUERY TAKES LONG TIME TO FINISH ... PLEASE HELP.
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
Upvotes: 1
Views: 1566
Reputation: 8832
Try this, instead of #tbl
put your table name:
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]
Upvotes: 1