mysql select sum(row1)
4 отговора
126 прегледа
mysql select sum(row1)
Имам един ред в таблицата.Полетата са тип float(4,2)
select payed,total from tbl1
| payed | total |
+-------+--------+
| 0 | 206.15 |
+-------+--------+
До тук ОК; сега обаче :
select sum(payed),sum(total) from tbl1;
+------------+-----------------+
| sum(payed) | sum(total) |
+------------+-----------------+
| 0 | 206.14999389648 |
+------------+-----------------+
Много странна стойност за второ поле ?! Защо се получава така ?Не че е проблем но ми е интересно.
select sum(payed),round(sum(total),2) as summ from tbl1;
и всичко се оправя но не е там въпроса.
select payed,total from tbl1
| payed | total |
+-------+--------+
| 0 | 206.15 |
+-------+--------+
До тук ОК; сега обаче :
select sum(payed),sum(total) from tbl1;
+------------+-----------------+
| sum(payed) | sum(total) |
+------------+-----------------+
| 0 | 206.14999389648 |
+------------+-----------------+
Много странна стойност за второ поле ?! Защо се получава така ?Не че е проблем но ми е интересно.
select sum(payed),round(sum(total),2) as summ from tbl1;
и всичко се оправя но не е там въпроса.
Re: mysql select sum(row1)
Обикновено SUM каства до флоат. Вероятно така е и в MySQL.
Re: mysql select sum(row1)
Защото всички операции с тип float се извършват с "аритметика с плаваща запетая" т.е. винаги са приблизителни. Всъщност как точно се съхранява в таблицата числото 206.15 зависи от много неща но най-общо изобщо не е задължително да е 206.15 а по вероятно е нещо в стил 206.14999389648 което и получаваш като резултат от SUM()
Също както 3.0 вможе да се окаже 2.99999999999999945356265 например.
Тъй като полето ти е дефинирано като float(4,2) MySQL "знае", че трябва да закръгли до втория десетичен знак при
select payed,total from tbl1;
При
select sum(payed),sum(total) from tbl1;
обаче си няма идея каква точност ти трябва.
В случая трябва да използаш някоя от функциите за закръгляване като примерно
select round(sum(total), 2) from tbl1;
Като цяло обаче се сблъскваш с добре известния факт, че аритметиката с плаваща запетая е НЕТОЧНА.
Например правилото (a / b) * b = a при аритметика с плаваща запетая почти никога не е вярно!
както и да речем sum(a * b) = sum(a) * sum(b)
Тъй, че не се изненадвай от ефекти като:
mysql> select a, b, round(a, 10), round(b, 10) from newbie;
+------+--------+--------------+----------------+
| a | b | round(a, 10) | round(b, 10) |
+------+--------+--------------+----------------+
| 0.10 | 206.15 | 0.1000000015 | 206.1499938965 |
+------+--------+--------------+----------------+
съответно:
mysql> select @x:=round(sum(a+b), 20), @y:=round(sum(a), 20) + round(sum(b), 20)from newbie;
+--------------------------+-------------------------------------------+
| @x:=round(sum(a+b), 20) | @y:=round(sum(a), 20) + round(sum(b), 20) |
+--------------------------+-------------------------------------------+
| 206.24999389797446269768 | 206.24999389797451954109 |
+--------------------------+-------------------------------------------+
mysql> select @x = @y, @x - @y;
+---------+----------------------+
| @x = @y | @x - @y |
+---------+----------------------+
| 0 | -5.6843418860808e-14 |
+---------+----------------------+
0 => false
и така нататък.
Както и документацията на MySQL препоръчва ако ти трябва точно изчисление трябва или да използваш тип DECIMAL (който се съхранява като стринг с фиксирана запетая) или да преобразиваш всичко до INTEGER примерно да разбиеш на две колонки или пак да умножаваш по 100 и да пазиш всичко като "стотинки"
Всъщност това отговаря на спецификацията на SQL-99
salle.online.bg/sig
Също както 3.0 вможе да се окаже 2.99999999999999945356265 например.
Тъй като полето ти е дефинирано като float(4,2) MySQL "знае", че трябва да закръгли до втория десетичен знак при
select payed,total from tbl1;
При
select sum(payed),sum(total) from tbl1;
обаче си няма идея каква точност ти трябва.
В случая трябва да използаш някоя от функциите за закръгляване като примерно
select round(sum(total), 2) from tbl1;
Като цяло обаче се сблъскваш с добре известния факт, че аритметиката с плаваща запетая е НЕТОЧНА.
Например правилото (a / b) * b = a при аритметика с плаваща запетая почти никога не е вярно!
както и да речем sum(a * b) = sum(a) * sum(b)
Тъй, че не се изненадвай от ефекти като:
mysql> select a, b, round(a, 10), round(b, 10) from newbie;
+------+--------+--------------+----------------+
| a | b | round(a, 10) | round(b, 10) |
+------+--------+--------------+----------------+
| 0.10 | 206.15 | 0.1000000015 | 206.1499938965 |
+------+--------+--------------+----------------+
съответно:
mysql> select @x:=round(sum(a+b), 20), @y:=round(sum(a), 20) + round(sum(b), 20)from newbie;
+--------------------------+-------------------------------------------+
| @x:=round(sum(a+b), 20) | @y:=round(sum(a), 20) + round(sum(b), 20) |
+--------------------------+-------------------------------------------+
| 206.24999389797446269768 | 206.24999389797451954109 |
+--------------------------+-------------------------------------------+
mysql> select @x = @y, @x - @y;
+---------+----------------------+
| @x = @y | @x - @y |
+---------+----------------------+
| 0 | -5.6843418860808e-14 |
+---------+----------------------+
0 => false
и така нататък.
Както и документацията на MySQL препоръчва ако ти трябва точно изчисление трябва или да използваш тип DECIMAL (който се съхранява като стринг с фиксирана запетая) или да преобразиваш всичко до INTEGER примерно да разбиеш на две колонки или пак да умножаваш по 100 и да пазиш всичко като "стотинки"
Всъщност това отговаря на спецификацията на SQL-99
salle.online.bg/sig
Re: mysql select sum(row1)
Само една забележка:
>>>
...почти никога не е вярно! ....
както и да речем sum(a * b) = sum(a) * sum(b)
...
<<<
Израза:
sum(a * b) = sum(a) * sum(b)
не е верен и в математиката.
Предполагам, че е написан по инерция.
>>>
...почти никога не е вярно! ....
както и да речем sum(a * b) = sum(a) * sum(b)
...
<<<
Израза:
sum(a * b) = sum(a) * sum(b)
не е верен и в математиката.
Предполагам, че е написан по инерция.
Re: s/*/+/g
Или с други думи * да се чете +
т.е. sum(a + b) != sum(a) + sum(b)
Абе човек като е уморен трябва да спи а не да пише глупости.
Благодаря за забележката.
salle.online.bg/sig
т.е. sum(a + b) != sum(a) + sum(b)
Абе човек като е уморен трябва да спи а не да пише глупости.
Благодаря за забележката.
salle.online.bg/sig