是否可以在数据库中使用case语句+ round()

时间:2019-02-17 04:48:08

标签: mysql database mariadb

我有一个名为“ 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天的时间来解决问题,但仍然不知道,请帮忙

1 个答案:

答案 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,因为一个是二进制的,一个是十进制的。因此,我通常建议使用FLOATDOUBLE作为“货币”。

假设您的真实目标是将货币值表示为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:...