【问题标题】:How do I sum datetimes without a cursor?如何在没有光标的情况下对日期时间求和?
【发布时间】:2018-02-10 03:50:01
【问题描述】:

最佳实践问题。我有一张DATED, AgentName, Available_Time (DATETIME) 的桌子。日期不是连续的,例如缺少所有周末,同样AgentName 并非每天都存在。

我试图在给定的日期范围内为每个用户获取SUMAVG。目前,我有一个浏览所有可用日期的光标,里面是另一个浏览该日期所有名称的光标。我曾希望使用SUM(COLUMN),但你不能用DATETIME 做到这一点,你只能使用COLUMN + COLUMN。我尝试转换为TIME,它可以工作,除非它总计超过 24 小时,它会回滚到 00:00:000 并且我失去了时间。我在想CTE,但仍然无法使用sum。下面的代码基本上是对其进行建模,但显然给我的是行而不是总和。数据集很小,所以游标不是问题,我只是不喜欢它们:)。想法?

if OBJECT_ID('tempdb..#RESULTS') is not null
    drop table #RESULTS;

CREATE TABLE #RESULTS (AgentName NVARCHAR(100)
                        ,DATED DATE
                        ,Available_Time DATETIME
                        )

INSERT INTO #RESULTS 
VALUES 
('007','1/1/2018','1900/01/01 02:33:51')
,('007','1/2/2018','1900/01/01 00:32:37')
,('007','1/3/2018','1900/01/01 01:02:54')
,('007','1/4/2018','1900/01/01 01:22:14')
,('007','1/5/2018','1900/01/01 01:48:42')
,('007','1/7/2018','1900/01/01 01:16:07')
,('007','1/9/2018','1900/01/01 02:25:56')
,('007','1/11/2018','1900/01/01 02:00:09')
,('007','1/13/2018','1900/01/01 12:36:01')
,('007','1/15/2018','1900/01/01 11:56:25')
,('K','1/11/2018','1900/01/01 02:00:09')
,('K','1/13/2018','1900/01/01 12:36:01')
,('K','1/15/2018','1900/01/01 11:56:25')

if OBJECT_ID('tempdb..#RESULTS2') is not null
    drop table #RESULTS2;

CREATE TABLE #RESULTS2 (RNUMBER INT
                        ,AgentName NVARCHAR(100)
                        --,DATED DATE
                        ,Available_Time DATETIME
                        )

INSERT INTO #RESULTS2
SELECT  ROW_NUMBER() OVER (PARTITION BY AGENTNAME ORDER BY DATED) RNUM
        ,AgentName
        --,DATED
        ,Available_Time
from #RESULTS
;

WITH DATEAGG AS 
(SELECT * 
FROM #RESULTS2
)

SELECT d.AgentName 
        ,d.Available_Time + d2.Available_Time - '1900-01-01 00:00:00.000'
FROM DATEAGG d
LEFT JOIN DATEAGG d2
on d.AgentName = d2.AgentName
and d.RNUMBER = d2.RNUMBER +1

所以最终输出(这是不正确的,但)看起来像:

Agent  | Total Time 
007    |  1900/01/02 11:54:23 
K      |  1900/01/01 01:54:23

从那里我可以轻松地 DATEDIFF(ss,1900/01/01,RESULT) 并获得总时间。 最终答案类似于(取决于我的格式)

Agent  | Total Time 
007    |  2D 11:54:23 
K      |  0D 01:54:23

【问题讨论】:

  • 那么日期和时间是日期字段和日期时间字段的组合,其中日期从后者中剥离?您可以先将日期转换为数字。不确定这是否是理想的方式。
  • 不清楚您要聚合什么。也许如果您将代码包含在您提到的光标中
  • 您在发布 ddl 和示例数据方面做得很好。不幸的是,这里所需的输出像泥浆一样清晰。你能发布你期望的输出吗,也许是对到达那里的逻辑的解释?
  • 为清楚起见,抱歉编辑。
  • 你可以改变你的表结构吗?因为我很确定你做错了。 AvailableTime 是一天中的实际时间,还是时间量?我假设是后者,因为“总结”一天中时间的想法很愚蠢。

标签: sql sql-server sql-server-2012


【解决方案1】:

DateTime 数据类型用于存储时间点,而不是时间量或持续时间。尝试将持续时间(或时间量)存储为日期时间会导致您遇到的那种混乱。

时间量是一个数字。将它存储在数据库中的最佳方法是存储一个整数,该整数包含您有兴趣测量的时间的最低细分。在你的情况下,它看起来像几秒钟。因此,与其存储包含“1900/01/01 00:01:00”的 DateTime,不如存储一个包含“60”的整数。

然后很容易进行 SUM、AVG 或执行您可能想要的任何其他数学运算,当需要以天、小时、分钟和秒表示结果时,您可以在查询时执行数学和字符串格式化。

【讨论】:

  • 我很高兴你知道了这一点。对于我的生活来说,这根本没有意义。一旦你指出了持续时间部分,它终于点击了。
  • 我相信您是正确的,这就是为什么即使 Excel 也将所有内容都存储为整数的原因,一旦我完成,我会回来标记这个正确的。谢谢
猜你喜欢
  • 2020-01-07
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
  • 1970-01-01
相关资源
最近更新 更多