【问题标题】:SQL select hours from two time fields but between a rangeSQL 从两个时间字段但在一个范围之间选择小时
【发布时间】:2018-05-20 01:41:04
【问题描述】:

我使用的是 SQL Server 2014,在问这里之前我已经尝试了几件事。

我需要完成的是: 我有一个存储两个时间列的表,它们的值例如 9:00 或 2:34 等。

我需要计算每天的工作时间和夜间工作时间。 每天的时间必须从 8:00 到 20:00 计算,夜间的时间必须从 20:00 到 8:00 计算

如果我有两个时间字段,那么值可以是

4:00 和 12:00

12:00 和 20:00

22:00 和 6:00

我想要做的是检索对应于每日时间和夜间时间的两个十进制值,也许有一个 SQL 函数我不知道哪个传递两个值和一个范围为我完成这项任务,或者也许是我自己建一个的情况

【问题讨论】:

  • 表格有,而不是字段。
  • 你说得对,我使用的是 SQL Server 2014,是的,列不是字段
  • 这两列的数据类型是TIME吗?
  • @Cool_Br33ze 是的,它只是一个时间字段,你建议使用 datetime 吗?
  • 是的,使用 DATETIME 或 DATETIME2 让计算变得容易得多。

标签: sql sql-server tsql time type-conversion


【解决方案1】:

我认为你可以使用辅助表

CREATE TABLE HourInfo(
  h time NOT NULL,
  isNight bit NOT NULL
CONSTRAINT PK_HourInfo PRIMARY KEY(h)
)
GO

INSERT HourInfo(h,isNight)VALUES
('00:00',1),('01:00',1),('02:00',1),('03:00',1),('04:00',1),('05:00',1),('06:00',1),('07:00',1),('08:00',1),
('09:00',0),('10:00',0),('11:00',0),('12:00',0),('13:00',0),('14:00',0),('15:00',0),('16:00',0),('17:00',0),('18:00',0),('19:00',0),
('20:00',1),('21:00',1),('22:00',1),('23:00',1)
GO

CREATE TABLE MinuteInfo(
  m time NOT NULL,
  isNight bit NOT NULL
CONSTRAINT PK_MinuteInfo PRIMARY KEY(m)
)
GO

INSERT MinuteInfo(m,isNight)
SELECT DATEADD(MINUTE,m.m,h.h) m,h.isNight
FROM HourInfo h
CROSS JOIN
  (
    SELECT i*10+j AS m
    FROM (VALUES(0),(1),(2),(3),(4),(5)) n1(i)
    CROSS JOIN (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) n2(j)
  ) m
GO

并使用以下查询

SELECT CAST('04:00' AS time) t1,CAST('12:00' AS time) t2 INTO #TestData
UNION ALL
SELECT CAST('12:00' AS time) t1,CAST('20:00' AS time) t2
UNION ALL
SELECT CAST('22:00' AS time) t1,CAST('06:00' AS time) t2
UNION ALL
SELECT CAST('00:00' AS time) t1,CAST('05:15' AS time) t2

/*
SELECT
  d.t1,
  d.t2,
  COUNT(CASE WHEN h.isNight=1 THEN 1 END) [night hours],
  COUNT(CASE WHEN h.isNight=0 THEN 1 END) [daily hours]
FROM #TestData d
JOIN HourInfo h
ON
     (d.t1>d.t2 AND ((h.h>=d.t1 AND h.h<=CAST('23:00' AS time)) OR (h.h>=CAST('00:00' AS time) AND h.h<d.t2)))
  OR (d.t1<=d.t2 AND h.h>=d.t1 AND h.h<=d.t2)
GROUP BY d.t1,d.t2
*/

SELECT
  d.t1,
  d.t2,
  COUNT(CASE WHEN m.isNight=1 THEN 1 END)/60. [night hours],
  COUNT(CASE WHEN m.isNight=0 THEN 1 END)/60. [daily hours]
FROM #TestData d
JOIN MinuteInfo m
ON
     (d.t1>d.t2 AND ((m.m>=d.t1 AND m.m<=CAST('23:59' AS time)) OR (m.m>=CAST('00:00' AS time) AND m.m<d.t2)))
  OR (d.t1<=d.t2 AND m.m>=d.t1 AND m.m<d.t2)
GROUP BY d.t1,d.t2

DROP TABLE #TestData

【讨论】:

  • 我认为你误解了我的任务。我不需要从 4:00 到 12:00 的某些值,这些只是示例,这两列可以存储每个可能的值,我需要计算一个范围内的小时数。如果我有 5:25 和 9:00,我需要从 5:25 到 8:00 算作夜间时间,从 8:00 到 9:00 算作每天的时间
  • 5:25 till 8:00 需要得到什么结果?是小时还是分钟?
  • 我创建了第二张表MinuteInfo 并使用HourInfo 填充它。
  • 必须是表示小时和分钟的小数,例如 5 小时 15 分钟必须是 5.25
  • 尝试检查我的最后一个查询。我认为它可以满足您的需求 - (5*60+15)/60 = 5.25.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多