#mysql #rounding #percentage
#mysql #округление #процент
Вопрос:
У меня есть таблица t(int, float, float, float)
в базе данных MySQL со следующими значениями:
ID | v1 | v2 | v3 |
---|---|---|---|
1 | 0.25 | 0.75 | 0 |
2 | 0.125 | 0 | 0.875 |
Гарантируется, что v1 v2 v3 ==1 для каждой строки.
Примечание: v1, v2 и v3 являются числами с плавающей запятой, поэтому в некоторых случаях v1 v2 v3 может быть 1 /- 1E-38
Мне нужно сгенерировать целочисленные проценты на выходе (т. Е. Целые числа от 0 до 100), которые бы добавляли до 100 для каждой записи и в то же время представляли исходные значения как можно точнее.
Для приведенной выше выборки данных ожидаемый результат будет либо:
ID | p1 | p2 | p3 |
---|---|---|---|
1 | 25 | 75 | 0 |
2 | 13 | 0 | 87 |
Или:
ID | p1 | p2 | p3 |
---|---|---|---|
1 | 25 | 75 | 0 |
2 | 12 | 0 | 88 |
(оба вышеуказанных вывода приемлемы)
Мое текущее решение:
Шаг 1: вычисление p1tmp = round(100*v1), p2tmp = round(100*v2), p3tmp = round(100*v3)
Шаг 2: вычисление:
p1 = CASE
WHEN p1tmp = GREATEST(p1tmp, p2tmp, p3tmp) AND GREATEST(p1tmp, p2tmp, p3tmp) > LEAST(p1tmp, p2tmp, p3tmp)
THEN 100 - p2tmp - p3tmp ELSE p1tmp END AS p1,
p2 = CASE
WHEN p2tmp = GREATEST(p1tmp, p2tmp, p3tmp) AND GREATEST(p1tmp, p2tmp, p3tmp) > LEAST(p1tmp, p2tmp, p3tmp)
THEN 100 - p1tmp - p3tmp ELSE p2tmp END AS p2,
p3 = CASE
WHEN p3tmp = GREATEST(p1tmp, p2tmp, p3tmp) AND GREATEST(p1tmp, p2tmp, p3tmp) > LEAST(p1tmp, p2tmp, p3tmp)
THEN 100 - p1tmp - p2tmp ELSE p3tmp END AS p3
Несмотря на математическую корректность, приведенное выше решение не очень элегантно. Код запутанный, нечитаемый и его нелегко расширить до случая с 4 или 5 значениями (мое текущее требование — 4 значения, т.Е. v1, v2, v3, v4, но оно может измениться в будущем).
Я попытался применить метод округления до ближайшего четного, но он работал только для пары переменных (т.Е. v1, v2, а не v1, v2, v3).
Любые идеи приветствуются.
Комментарии:
1. Разве не гарантируется, что один v будет равен нулю?
2. Нет. Любое количество Vs может быть ненулевым для любой отдельной записи.
Ответ №1:
Решение MSSQL, но может быть легко принято. — сделайте сводку
declare @id int
set @id =4 -- take a single row data
create table #row(x float, procent int, col int);
insert into #row
select v1,0,1 from t where id = @id union all
select v2,0,2 from t where id = @id union all
select v3,0,3 from t where id = @id;
with cte as
(select x,
case when x != (select max(x) from #row) then ROUND(x*100,0) else ROUND(x*100,0,1) end x2
from #row )
select * from cte -- unpivoto
drop table #row