Sql server 2008 两个日期之间的分钟数取决于状态
我有一个关于SQLServer2005(Tsql)的问题 我有两个专栏 日期 地位 数据看起来。。像Sql server 2008 两个日期之间的分钟数取决于状态,sql-server-2008,sql-server-2005,Sql Server 2008,Sql Server 2005,我有一个关于SQLServer2005(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-
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
试试这个,而不是
#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]
试试这个,而不是
#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]
请添加已编写的查询。是否使用光标?这些都不是很有效。这些列有索引吗?发布您尝试的TSQL。我也通过查询发布了。。。并在需要的地方进行注释。请添加您编写的查询。是否使用光标?这些都不是很有效。这些列有索引吗?发布您尝试的TSQL。我也通过查询发布了。。。并在任何需要的地方发表评论谢谢你,你很快。。数据中的细微变化有时您将无法获得状态2,它将是('2012-09-01 00:01:00.000',4),一天的结束将是('2012-09-01 23:59:00.000',4),因此它们的开始将是第一条记录,结束将是最后一条记录,在这两者之间,您可能还有2和1。。你能帮忙吗。。请Hi ivan,我已经对你的查询发表了评论,你能看一看吗?你对此有什么想法吗?我添加了新的功能,现在查询有点大,它处理状态2和1(分别)的情况,以及全天没有状态2或1的情况(我添加此情况是为了测试数据)。这些是唯一可能的情况吗?是否存在一种情况,例如,状态1后接状态2,或者全天只有状态1?没有其他可能的情况。。我已将您的查询分解为临时表,并执行它。。然而,当我运行它们时,使用cte需要10分钟以上的时间,我认为我每个单元有706条记录到1500条记录,表中有超过百万条记录。。而且速度要慢得多。。。任何想法…我注意到了同样的事情,有时当我使用表变量或CTE而不是临时表时,使用它们的查询速度会减慢很多,我不知道这是什么原因…谢谢你很快。。数据中的细微变化有时您将无法获得状态2,它将是('2012-09-01 00:01:00.000',4),一天的结束将是('2012-09-01 23:59:00.000',4),因此它们的开始将是第一条记录,结束将是最后一条记录,在这两者之间,您可能还有2和1。。你能帮忙吗。。请Hi ivan,我已经对你的查询发表了评论,你能看一看吗?你对此有什么想法吗?我添加了新的功能,现在查询有点大,它处理状态2和1(分别)的情况,以及全天没有状态2或1的情况(我添加此情况是为了测试数据)。这些是唯一可能的情况吗?是否存在一种情况,例如,状态1后接状态2,或者全天只有状态1?没有其他可能的情况。。我已将您的查询分解为临时表,并执行它。。然而,当我运行它们时,使用cte需要10分钟以上的时间,我认为我每个单元有706条记录到1500条记录,表中有超过百万条记录。。而且速度要慢得多。。。任何想法…我注意到同样的事情,有时当我使用表变量或CTE而不是临时表时,使用它们的查询速度会减慢很多,我不知道这是什么原因。。。