我有一个名为“ test”的表,并希望根据不同的代码进行计算,除某些代码外,大多数代码应保存为5个小数,例如jpy包含3个小数,xua包含2个小数。
create table test(
id int, ymd date,
code varchar(10),
price int
)
insert into test(id, ymd, code, price) values
(1, '2019-01-01', 'auus', 75125),
(2, '2019-01-02', 'nzus', 68541),
(3, '2019-01-03', 'xuaus', 131485),
(4, '2019-01-04', 'aujp', 77852),
(5, '2019-01-05', 'usjp', 110852),
(6, '2019-01-06', 'xuaus', 131091)
所以我的执行代码是:
select id, ymd, code, price,
case
when code like '%xua%' then round(price/100,2)
when code like '%jp%' then round(price/1000,3)
else round(price/100000,5)
end as t
from test
理想结果:
id ymd code price t
1 2019-01-01 auus 75125 0.75125
2 2019-01-02 nzus 68541 0.68541
3 2019-01-03 xuaus 131485 1314.85
4 2019-01-04 aujp 77852 77.852
5 2019-01-05 usjp 110852 110.852
6 2019-01-06 xuaus 131091 1310.91
有趣的是,上面的sql在Mysql上很好用,但是我正在使用mariadb,但是无法获得与mysql相同的结果,花了2天的时间来解决问题,但仍然不知道,请帮忙
答案 0 :(得分:1)
mysql> select id, ymd, code, price,
-> case
-> when code like '%xua%' then round(price/100,2)
-> when code like '%jp%' then round(price/1000,3)
-> else round(price/100000,5)
-> end as t
-> from test ;
+------+------------+-------+--------+------------+
| id | ymd | code | price | t |
+------+------------+-------+--------+------------+
| 1 | 2019-01-01 | auus | 75125 | 0.75125 |
| 2 | 2019-01-02 | nzus | 68541 | 0.68541 |
| 3 | 2019-01-03 | xuaus | 131485 | 1314.85000 |
| 4 | 2019-01-04 | aujp | 77852 | 77.85200 |
| 5 | 2019-01-05 | usjp | 110852 | 110.85200 |
| 6 | 2019-01-06 | xuaus | 131091 | 1310.91000 |
+------+------------+-------+--------+------------+
6 rows in set (0.04 sec)
使用FORMAT
代替ROUND
:
mysql> select id, ymd, code, price,
case when code like '%xua%' then format(price/100,2)
when code like '%jp%' then format(price/1000,3)
else format(price/100000,5) end as t from test;
+------+------------+-------+--------+----------+
| id | ymd | code | price | t |
+------+------------+-------+--------+----------+
| 1 | 2019-01-01 | auus | 75125 | 0.75125 |
| 2 | 2019-01-02 | nzus | 68541 | 0.68541 |
| 3 | 2019-01-03 | xuaus | 131485 | 1,314.85 |
| 4 | 2019-01-04 | aujp | 77852 | 77.852 |
| 5 | 2019-01-05 | usjp | 110852 | 110.852 |
| 6 | 2019-01-06 | xuaus | 131091 | 1,310.91 |
+------+------------+-------+--------+----------+
6 rows in set (0.00 sec)
mysql> select @@version;
+----------------------------------------+
| @@version |
+----------------------------------------+
| 10.3.11-MariaDB-1:10.3.11+maria~bionic |
+----------------------------------------+
1 row in set (0.00 sec)
请注意,在适当时,它包括一个“千位分隔符”。请参见FORMAT()
的第3个参数或“语言环境”设置来更改它。
我怀疑是 display 进程正在以不同的方式格式化输出。通过从ROUND
切换到FORMAT
,我设法使MariaDB的输出与MySQL的输出几乎相同。剩下的区别是添加的逗号(“千位分隔符”),可能显示为“。”。对于某些语言环境。
相比之下,对于MySQL 5.6.22:
+------+------------+-------+--------+---------+
| id | ymd | code | price | t |
+------+------------+-------+--------+---------+
| 1 | 2019-01-01 | auus | 75125 | 0.75125 |
| 2 | 2019-01-02 | nzus | 68541 | 0.68541 |
| 3 | 2019-01-03 | xuaus | 131485 | 1314.85 |
| 4 | 2019-01-04 | aujp | 77852 | 77.852 |
| 5 | 2019-01-05 | usjp | 110852 | 110.852 |
| 6 | 2019-01-06 | xuaus | 131091 | 1310.91 |
+------+------------+-------+--------+---------+
数字值相同,但显示不同。差异似乎来自命令行工具mysql
,而不是ROUND
本身。请注意,t
是右对齐的,这意味着这些值被视为数字。
如果这足以冒犯某人,请向MariaDB提交错误报告。
77.75200000000001
-代表使用DOUBLE
而不是全部DECIMAL
进行的一些中间计算。 MySQL(和MariaDB)在猜测数字的去向方面做得相当好。而且通常他们会做任何事而逃脱。
在DOUBLE
中,77.75200000000001
并不完全等于DECIMAL
77.752
,因为一个是二进制的,一个是十进制的。因此,我通常建议不使用FLOAT
或DOUBLE
作为“货币”。
假设您的真实目标是将货币值表示为77.7520000000000000000000000...
,即恰好是“ 77.752”,并且假设您最多需要将5个小数位用于各个值,我建议您这样做:>
t DECIMAL(m, 5)
其中m
对于您最终可能拥有的任何值都是一个适当的大数字。对于给出的数字,(9,5)
就足够了,但我怀疑您应该做更多类似DECIMAL(14,5)
的工作,以允许10亿美元/欧元/日元/等。
我不知道在处理DOUBLE
时是在什么地方进行的。
最新的“建议”
DECIMAL(14,5)
用于系统中的所有货币值,而不是INT
。14,5
可让您获得多达十亿美元的“美元”;更改所需的期望最大值。FORMAT()
的评论;似乎太令人困惑了。CASE
子句。DECIMAL
个值中的大多数算术运算都是精确的,不会遇到77.75200000000001
。如果再次出现,请开始一个新的Question并包括计算中涉及的所有步骤,数据类型等。方案A:5位小数即可。
方案B:某些值需要四舍五入到3或2个小数。
方案C:您拥有可以解决此问题的应用程序代码,而不是SQL。
计划D:...