0

我有一个公式设置,它采用小数,即 a 基数 103.6 three hours and point 6 minutes并将小数位转换为基数 60 36 minutes。然后它使用上限将分钟四舍五入到最接近的 15 分钟增量,因此它总是四舍五入36 to 45 minutes。然后它将小时部分与分钟部分连接起来,并在它们之间放置一个字符串冒号。这个 sql 在视图中执行。

现在在视图中,它以十六进制值而不是字符串值的形式出现8:30 turns into 0x383A333020483A4D。但在选择查询中,它是正确的连接字符串格式。到底是怎么回事?

CONCAT((((CEILING(((60 * ((agent_logins.hours_worked) % 1)) / 15)) * 15) / 60) + ((agent_logins.hours_worked) - ((agent_logins.hours_worked) % 1))) - (((CEILING(((60 * ((agent_logins.hours_worked) % 1)) / 15)) * 15) / 60) + ((agent_logins.hours_worked) - ((agent_logins.hours_worked) % 1))) % 1, ':', (((CEILING(((60 * ((agent_logins.hours_worked) % 1)) / 15)) * 15) / 60) + ((agent_logins.hours_worked) - ((agent_logins.hours_worked) % 1))) % 1 * 60) as hours_worked
4

3 回答 3

1

如下所述CONCAT()

如果参数包含任何二进制字符串,则结果为二进制字符串。一个数字参数被转换成它的等效字符串形式。从 MySQL 5.5.3 开始,这是一个非二进制字符串。5.5.3之前是二进制字符串;为避免这种情况并生成非二进制字符串,您可以使用显式类型转换,如下例所示:

SELECT CONCAT(CAST(int_col AS CHAR), char_col);

您必须使用 5.5.3 之前的 MySQL 版本,因此将数字参数CONCAT()转换为二进制字符串(导致整体二进制字符串)。您的客户端以十六进制形式向您显示二进制列,这是一种合理的行为。

正如文档所说(以及@SofianeM's answerCONVERT()中所建议的),您可以通过使用or显式转换回非二进制字符串来克服这个问题CAST()

但是,为什么不简单地使用SEC_TO_TIME()

SELECT SEC_TO_TIME(CEILING(4 * hours_worked) * 900)
FROM   agent_logins

sqlfiddle上查看。

于 2012-12-13T23:43:36.013 回答
1

该十六进制表示的前四个字节似乎代表了您预期的字符串值的 ASCII 编码'8:30'。接下来的四个字节出现在 ASCII 编码中,表示' H:M'.

0x38 = '8'
0x3A = ':'
0x33 = '3'
0x30 = '0'
0x20 = ' '
0x48 = 'H'
0x3A = ':'
0x4D = 'M'

这并不能真正回答您提出的问题,但是...

为什么不使用 MySQL 内置函数来进行这种类型的格式化?(一种可能的解释是您需要使用的“持续时间”值超出了 MySQLTIME数据类型允许的限制,即 -838:59:59 到 838:59:59。)

否则,您可以使用更简单的表达式将时间四舍五入到最接近的 15 分钟边界,并将其格式化为小时:分钟的字符串表示形式

TIME_FORMAT(SEC_TO_TIME(CEILING( agent_login.hours_worked *4)*900),'%k:%i')

SQL小提琴在这里


完全不清楚为什么使用视图作为行源的 SELECT 语句会返回八个字符,而 SELECT 生成的字符串应该只有四个字符,或者为什么客户端会选择显示十六进制表示。(八个字节恰好是 a 的长度BIGINT。)

于 2012-12-13T23:56:50.110 回答
0

Convert(exp, type)解决了这个问题。转换

于 2012-12-13T23:23:04.720 回答