можно ли использовать оператор case + round () в базе данных - PullRequest
0 голосов
/ 17 февраля 2019

У меня есть таблица с именем «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

intersting, выше sql хорошо работает с Mysql, но я использую mariadb и просто не могуполучить результаты так же, как MySQL, потратил 2 дня, чтобы решить проблему, но все еще не знаю, пожалуйста, помогите

1 Ответ

0 голосов
/ 17 февраля 2019
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: ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...