我有一个公式设置,它采用小数,即基数10 3.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
答案 0 :(得分: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 answer中的建议),您可以通过显式转换回CONVERT()
或CAST()
的非二进制字符串来克服此问题。
但是,为什么不简单地使用SEC_TO_TIME()
?
SELECT SEC_TO_TIME(CEILING(4 * hours_worked) * 900)
FROM agent_logins
在sqlfiddle上查看。
答案 1 :(得分:1)
该十六进制表示的前四个字节似乎表示您期望的字符串值'8:30'
的ASCII编码。接下来的四个字节显示为代表' H:M'
的ASCII编码。
0x38 = '8'
0x3A = ':'
0x33 = '3'
0x30 = '0'
0x20 = ' '
0x48 = 'H'
0x3A = ':'
0x4D = 'M'
这并没有真正回答你问的问题,但是......
为什么不使用MySQL内置函数来执行此类格式化? (一种可能的解释是,您需要使用的“持续时间”值超出了MySQL TIME
数据类型允许的限制,即-838:59:59到838:59:59。)
否则,您可以使用更简单的表达式将时间向上舍入到最近的15分钟边界,并将其格式化为小时:分钟的字符串表示
TIME_FORMAT(SEC_TO_TIME(CEILING( agent_login.hours_worked *4)*900),'%k:%i')
当SELECT生成的字符串只有4个字符,或者客户端选择显示十六进制表示的原因时,使用视图作为行源的SELECT语句返回8个字符的原因一点也不清楚。 (八个字节确实恰好是BIGINT
的长度。)
答案 2 :(得分:0)
Convert(exp, type)
解决了这个问题。 Conversions