【问题标题】:Calculate the difference in alternate columns in time format?以时间格式计算交替列的差异?
【发布时间】:2016-03-16 08:05:07
【问题描述】:
Status  Date    Time
1   2016-03-16  8:00:00
0   2016-03-16  12:00:00
1   2016-03-16  16:00:00
0   2016-03-16  20:00:00
1   2016-03-16  23:55:00
0   2016-03-17  01:16:00
1   2016-03-17  02:20:00
0   2016-03-17  04:00:00
1   2016-03-17  08:00:00
0   2016-03-17  12:00:00
1   2016-03-17  04:00:00
0   2016-03-17  06:00:00

我有上面提到的表格。我想做的就是计算状态变化的时间之间的差异 例如,在前两列中,它应该返回 4 小时的时间差异 然后我不想计算第 2 列和第 3 列之间的差异我想计算第 3 列和第 4 列之间的差异等等...... 时差应采用时间格式,例如 4 小时或 58 分钟 总体而言,当状态从 1 变为 0 时,我将计算差异 请帮忙。

【问题讨论】:

  • 你确定总是有一个交替的行吗?不会丢失任何行(由于某种错误)?
  • SQL Server 还是 Access?它们非常不同。在 SQL Server 中,您可以使用 LAG 函数
  • 在 sql server 中相当简单,在 2012 或更高版本中更容易。在过去的 6-7 年里我没有使用 ms-access,所以我对此一无所知。
  • 另外,您有 2 行冲突,其中一个状态为 0,另一个状态为 1,时间为 2016 年 3 月 17 日 04:00:00。
  • 根据this comment编辑标签

标签: datetime ms-access-2007


【解决方案1】:

试试这样:

编辑:将 DATE 和 TIME 组合为 DATETIME 已更改为更简单的方式

DECLARE @tbl TABLE([Status] INT,  [Date] DATE,    [Time] TIME);
INSERT INTO @tbl VALUES
 (1,'2016-03-16','8:00:00')
,(0,'2016-03-16','12:00:00')
,(1,'2016-03-16','16:00:00')
,(0,'2016-03-16','20:00:00')
,(1,'2016-03-16','23:55:00')
,(0,'2016-03-17','01:16:00')
,(1,'2016-03-17','02:20:00')
,(0,'2016-03-17','04:00:00')
,(1,'2016-03-17','08:00:00')
,(0,'2016-03-17','12:00:00')
,(1,'2016-03-17','04:00:00')
,(0,'2016-03-17','06:00:00');

WITH AllStarts AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY [Date],[Time]) AS RowInx
          ,CAST([date] AS DATETIME)+CAST([time] AS DATETIME) AS TimePoint
    FROM @tbl
    WHERE [Status]=1
)
,AllEnds AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY [Date],[Time]) AS RowInx
          ,CAST([date] AS DATETIME)+CAST([time] AS DATETIME) AS TimePoint
    FROM @tbl
    WHERE [Status]=0
)
SELECT AllStarts.RowInx
      ,AllStarts.TimePoint AS StartPoint
      ,AllEnds.TimePoint AS [EndPoint]
      ,CAST(AllEnds.TimePoint - AllStarts.TimePoint AS TIME) AS TimeDiff
FROM AllStarts
INNER JOIN AllEnds ON AllStarts.RowInx=AllEnds.RowInx

结果:

1   2016-03-16 08:00:00.000    2016-03-16 12:00:00.000     04:00:00.0000000
2   2016-03-16 16:00:00.000    2016-03-16 20:00:00.000     04:00:00.0000000
3   2016-03-16 23:55:00.000    2016-03-17 01:16:00.000     01:21:00.0000000
4   2016-03-17 02:20:00.000    2016-03-17 04:00:00.000     01:40:00.0000000
5   2016-03-17 04:00:00.000    2016-03-17 06:00:00.000     02:00:00.0000000
6   2016-03-17 08:00:00.000    2016-03-17 12:00:00.000     04:00:00.0000000

【讨论】:

  • 数据库是动态的,我不能在这里硬编码值
  • @Lalit 此答案中没有硬编码值。
  • 这只是一个测试场景...您只能将表的名称@tbl 替换为您的实际表...
  • @Shnugo 1) 你可以使用cast(@Date as datetime) + cast(@Time as datetime) 作为shown here。 2) 使用LAG 将允许您在单个 CTE 中检索先前的值(和差异),然后按状态 0 过滤以仅获取结束行
  • @PanagiotisKanavos 我使用 ms 访问权限
【解决方案2】:

适用于 sql server 2012+ 的简单解决方案,但它可能不适用于 ms-access 2007。

;WITH cte as
(
SELECT  [Status], 
        [Date], 
        [Time], 
        CAST([Date] as datetime) + CAST([Time] As datetime) As [datetime]
FROM MyTable 
WHERE [Date] >= @StartDate
AND [Date] <= @EndDate
)

SELECT  [Status], 
        [Date], 
        [Time], 
        CASE WHEN [Date] = LAG([Date]) OVER (ORDER BY [datetime]) THEN
            CAST(DATEADD(MINUTE, DATEDIFF(MINUTE, LAG([datetime]) OVER (ORDER BY [datetime]), [datetime]), '00:00:00') as time) 
        ELSE 
            NULL
        END
        As TimeDifference
FROM cte 

结果(基于提供的数据)

Status Date       Time             TimeDifference
------ ---------- ---------------- ----------------
1      2016-03-16 08:00:00.0000000 NULL
0      2016-03-16 12:00:00.0000000 04:00:00.0000000
1      2016-03-16 16:00:00.0000000 04:00:00.0000000
0      2016-03-16 20:00:00.0000000 04:00:00.0000000
1      2016-03-16 23:55:00.0000000 03:55:00.0000000
0      2016-03-17 01:16:00.0000000 01:21:00.0000000
1      2016-03-17 02:20:00.0000000 01:04:00.0000000
0      2016-03-17 04:00:00.0000000 01:40:00.0000000
1      2016-03-17 04:00:00.0000000 00:00:00.0000000
0      2016-03-17 06:00:00.0000000 02:00:00.0000000
1      2016-03-17 08:00:00.0000000 02:00:00.0000000
0      2016-03-17 12:00:00.0000000 04:00:00.0000000

【讨论】:

  • 请让我检查一下我没有 SQL 2012 将检查并更新你的答案 Thanxin Advance
  • 但是我想从 vb.net 表单中执行这个 CTE,并且会有开始日期和结束日期如何执行相同
  • 亲爱的@Zohar 0 2016-03-17 01:16:00.0000000 01:21:00.0000000 我不想显示这个记录如何去做
  • 我已经编辑了我的答案,以展示如何使用 cte 的 where 子句中的变量来选择表格的特定日期范围。您不想展示的唱片有什么特别之处?
  • 谢谢 Zohar 但是我有一个疑问,我不想计算日期变化时的差异,即 2016-03-16 的最后一条记录和 2016-03-17 的第一条记录,即 1 2016-03- 16 23:55:00.0000000 03:55:00.0000000 0 2016-03-17 01:16:00.0000000 01:21:00.0000000 请更新
猜你喜欢
  • 2023-03-10
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多