【问题标题】:SQL operand data type datetime / varchar is invalid for sum operatorSQL 操作数数据类型 datetime / varchar 对 sum 运算符无效
【发布时间】:2018-07-13 09:51:59
【问题描述】:

我试图从另一列中减去一列,然后对结果求和。但是,无论我更改什么,我都会不断收到标题中提到的两个错误之一。

从发布的所有其他问题中,我得出我的陈述应该是这样的:

SELECT SUM(EndTime-BeginTime) AS TotalTime FROM TimeRegister 
WHERE OrderNumber = 00000 AND Activity = 11111;

根据另一个主题的建议,我将声明更改为:

SELECT SUM(CONVERT(varchar(EndTime-BeginTime), 108)) AS TotalTime FROM TimeRegister 
WHERE OrderNumber = 00000 AND Activity = 11111;

但是,我仍然收到错误消息。 时间存储如下:

1-1-1900 7:30:00

感谢您的任何建议...


编辑 1: 哦,我在 Excel 中通过 ODBC for SQL 使用 Microsoft Query,有点像: Excel vlookup incorporating SQL table


编辑 2: 我更喜欢以 HH:MM 格式再次输出。

问题是,当我将完整的数据库复制到 Excel 时,一切正常。我可以减去列并总结。我只是不想每天手动操作....


我刚查了SQL数据库,该列是日期/时间类型的。

【问题讨论】:

  • 如果列是日期数据类型(应该如此),您可以使用DATEDIFF()
  • 问题是您首先将日期转换为文本。无论其他主题是什么,如果它建议将日期转换为文本可以解决任何问题,那就错了。你期望得到什么输出?分钟?秒? time 值?
  • 在生成 SUM(DATEDIFF(MINUTE,__converted_EndTime,__converted_BeginTime))之前尝试在日期时间中转换每一列
  • @SnakeFoot 你假设 OP 想要几分钟。这可能是一个不错的猜测。
  • 第一个查询是有效的标准 SQL。您使用的是哪种 DBMS 产品? “SQL”只是一种查询语言——每个关系数据库都是一个“SQL 数据库”

标签: sql sql-server datetime sum intervals


【解决方案1】:

首先,尝试通过转换为文本来解决日期或数字问题永远不会解决任何问题,它会增加其他问题,例如转换失败或意外结果。

SQL Server 没有时间间隔类型。如果减去两个 datetime 值,您会得到另一个 datetime 值,该值表示自 1900 年 1 月 1 日以来的偏移量。以下查询:

select getdate() - dateadd(d,-1,getdate())

将返回:

1900-01-02 00:00:00.000

1900-01-01 之后的一整天。

datetime 值不能相加。 SQL Server 确实有一个time 类型,但它只代表一天中的时间。即使today - yesterday 有效,将其转换为time 也会返回00:00

一个快速的解决方案是使用DATEDIFF 以所需的任何单位(小时、分钟、秒等)计算两个日期之间的差异。请注意,尽管DATEDIFF 返回跨越的间隔边界的数量。 DATEDIFF(DAY,...) 在昨天晚上 11 点到今天凌晨 1 点之间将返回 1,因为已跨越 1 天的边界。

你可以使用

SELECT sum(datediff(minute,EndTime,BeginTime)) AS TotalMinutes
FROM TimeRegister 
WHERE OrderNumber = 00000 AND Activity = 11111;

以分钟为单位计算差异并将其格式化为客户端上的时间间隔。

另一种选择是在求和之前将datetime 转换为float,然后返回日期时间:

SELECT cast( sum(cast(EndTime - BeginTime as datetime)) as datetime) AS TotalOffset
FROM TimeRegister 
WHERE OrderNumber = 00000 AND Activity = 11111;

2 天的持续时间将显示为:

1900-01-03 00:00:00.000

这是有效的,因为datetime 可以转换为浮点数,其整数部分表示从 1900-01-01 的偏移量,小数部分表示时间。

使用 C# 之类的语言编写的客户端确实支持间隔可以从中减去 1900-01-01 以返回实际持续时间,例如:

TimeSpan duration = sumResult - new DateTime(1900,1,1);

另一种选择是避免最终转换,只使用生成的float 值作为天数。

在 Excel 中显示

最后一个选项可能是在 Excel 中显示持续时间的最简单方法! Excel 日期实际上存储为浮点数。使它们显示为日期或时间的是单元格的格式。

您可以将单元格格式设置为[h]:mm:ss,以显示任何数字作为持续时间。 [] 很重要 - 没有它,Excel 将只显示“日期”的时间部分。

如果您在单元格中输入2h:mm:ss 将显示为0:00:00,而[h]:mm:ss 将显示48:00:00,48 小时。

尽管很陌生,

SELECT sum(cast(EndTime - BeginTime as datetime)) AS TotalDuration
FROM TimeRegister 
WHERE OrderNumber = 00000 AND Activity = 11111;

可能是在 Excel 中显示持续时间总和的最佳选择

【讨论】:

  • 相当彻底的答案,+1。也许警告说减法不适用于datetime2 数据可能会使它更加完整。
【解决方案2】:

你似乎想要datediff()

SELECT SUM(DATEDIFF(second, BeginTime, EndTime) AS TotalTime
FROM TimeRegister 
WHERE OrderNumber = 00000 AND Activity = 11111;

【讨论】:

    【解决方案3】:

    以下内容如何:

    WITH totalTime AS (
      SELECT SUM(DATEDIFF(second,  EndTime, BeginTime)) as TimeInSecond
      FROM TimeRegister 
      WHERE OrderNumber = 00000 AND Activity = 11111;
    )
    SELECT RIGHT('0' + CAST(TimeinSecond / 3600 AS VARCHAR),2) + ':' +
      RIGHT('0' + CAST((TimeinSecond / 60) % 60 AS VARCHAR),2) + ':' +
      RIGHT('0' + CAST(TimeinSecond % 60 AS VARCHAR),2) AS TimeElapsed
    FROM totalTime;
    

    在此解决方案中,将时间转换为秒,然后进行总计,然后转换为 HH:MM:SS。

    【讨论】:

    • 这行不通,也不会执行 OP 要求的操作 - 聚合时间。转换为文本是导致问题的首要原因。
    • 我怀疑这是 OP 试图做的,“根据另一个主题的建议”。虽然我没有解决提到的错误,但我相信这是解决问题的方法。
    • 当我使用该语句时,我得到一列作为回报,这部分是我想要的。现在我想总结一下那一栏,然后我又得到了错误......
    • @RobertHaa 转换为文本是错误。您无法通过额外的文本操作来解决它,这就是导致问题的原因。解释你想要什么 - 汇总持续时间。提供实际的字段类型。
    • @BarryPiccinni 它没有解决问题,它增加了另一个问题。它也不会返回正确的数据 - 尝试间隔 1 天。结果是 00:00。
    猜你喜欢
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多