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)
Обратите внимание, что при необходимости он включает разделитель тысяч.См. 3-й аргумент FORMAT()
или настройку Locale, чтобы изменить это.
Я подозреваю, что это процесс 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)
, чтобы учесть миллиард долларов / евро / иен / и т. Д.
Чего я не знаю, так это гдеобработка DOUBLE
закралась.
Последний 'совет'
- Используйте
DECIMAL(14,5)
для всех денежных значений в вашей системе, а не INT
. 14,5
позволяет получить до миллиарда долларов;при необходимости измените его для ожидаемого максимального значения. - Не обращайте внимания на мои комментарии о
FORMAT()
;это кажется слишком запутанным. - Избавьтесь от предложения
CASE
, по крайней мере, для этого конкретного использования. - Большинство арифметических значений из
DECIMAL
будут точными и не встретятся 77.75200000000001
.Если он возникнет снова, запустите новый Вопрос и включите все шаги, типы данных и т. Д., Участвующие в вычислении. - Приведенные выше примечания относятся к хранению и вычислениям.Для , отображающего , укажите следующие требования:
План A: 5 десятичных знаков в порядке.
План B: необходимо округлить до 3 или 2 десятичных знаков для некоторых значений.
План C: у вас есть код приложения, а не SQL, который может решить эту проблему.
План D: ...