如何在 MySQL 查询中避免浮点运算?
How to avoid floating-point arithmetic in a MySQL query?
假设我有两列,A 和 B,类型为 DECIMAL(9,2)
。
现在,假设我 运行 以下查询:
SELECT SUM(A) / SUM(B)
我的理解是这个除法不会通过浮点运算来完成,因为两列都是 DECIMAL
类型。这是正确的吗?
此外,假设我 运行 以下查询:
SELECT SUM(A) / SUM(B) * 100
100
将如何影响查询?这会以某种方式导致 MySQL 进行浮点运算吗?如果是这样,我该如何避免?
Will this somehow cause MySQL to do floating-point arithmetic?
我想说你应该参考 SQL 标准,但是 MySQL,可能不是计算实际情况的最可靠方法:)。
how can I avoid [unexpected float casts]?
我会做的是明确地将值设为适合您的类型:
SUM(A) / SUM(B) * CAST(100.0 AS DECIMAL(9,2))
明确并有助于为未来的你做文档。
How will the 100 affect the query? Will this somehow cause MySQL to do floating-point arithmetic? If so, how can I avoid it?
100 是一个精确值数字文字,这里我们用小数除以小数乘以小数(整数)=> 结果仍然是小数(但精度更高)。
Exact-value numeric literals have an integer part or fractional part, or both. They may be signed. Examples: 1, .2, 3.4, -5, -6.78, +9.10.
Approximate-value numeric literals are represented in scientific notation with a mantissa and exponent. Either or both parts may be signed. Examples: 1.2E3, 1.2E-3, -1.2E3, -1.2E-3.
Two numbers that look similar may be treated differently. For example, 2.34 is an exact-value (fixed-point) number, whereas 2.34E0 is an approximate-value (floating-point) number.
示例:
CREATE TABLE t(A DECIMAL(9,2), B DECIMAL(9,2));
CREATE TABLE r1 AS SELECT SUM(A) / SUM(B) AS result FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r1';
+--------------+---------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+---------------+
| result | decimal(37,6) |
+--------------+---------------+
CREATE TABLE r2 AS SELECT SUM(A) / SUM(B) * 100 AS result FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r2';
+--------------+---------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+---------------+
| result | decimal(40,6) |
+--------------+---------------+
现在使用近似值数字文字100E0
:
CREATE TABLE r3 AS SELECT SUM(A) / SUM(B) * 100E0 AS result FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r3';
+--------------+-------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+-------------+
| result | double |
+--------------+-------------+
值得注意的是,某些操作可能看起来完全相同但 return 不同的数据类型。例如:
CREATE TABLE r4 AS SELECT POWER(A,2) AS result, A*A AS result2 FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r4';
+--------------+---------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+---------------+
| result | double |
| result2 | decimal(18,4) |
+--------------+---------------+
与其讨论计算的细节,不如格式化结果。例如:
SELECT ROUND(100 * sum(...) / sum(...), 1) ...
这给了你小数点后一位的百分比。
当您需要“千位分隔符”(百分比不太可能)时,请参阅 FORMAT()
函数。
假设我有两列,A 和 B,类型为 DECIMAL(9,2)
。
现在,假设我 运行 以下查询:
SELECT SUM(A) / SUM(B)
我的理解是这个除法不会通过浮点运算来完成,因为两列都是 DECIMAL
类型。这是正确的吗?
此外,假设我 运行 以下查询:
SELECT SUM(A) / SUM(B) * 100
100
将如何影响查询?这会以某种方式导致 MySQL 进行浮点运算吗?如果是这样,我该如何避免?
Will this somehow cause MySQL to do floating-point arithmetic?
我想说你应该参考 SQL 标准,但是 MySQL,可能不是计算实际情况的最可靠方法:)。
how can I avoid [unexpected float casts]?
我会做的是明确地将值设为适合您的类型:
SUM(A) / SUM(B) * CAST(100.0 AS DECIMAL(9,2))
明确并有助于为未来的你做文档。
How will the 100 affect the query? Will this somehow cause MySQL to do floating-point arithmetic? If so, how can I avoid it?
100 是一个精确值数字文字,这里我们用小数除以小数乘以小数(整数)=> 结果仍然是小数(但精度更高)。
Exact-value numeric literals have an integer part or fractional part, or both. They may be signed. Examples: 1, .2, 3.4, -5, -6.78, +9.10.
Approximate-value numeric literals are represented in scientific notation with a mantissa and exponent. Either or both parts may be signed. Examples: 1.2E3, 1.2E-3, -1.2E3, -1.2E-3.
Two numbers that look similar may be treated differently. For example, 2.34 is an exact-value (fixed-point) number, whereas 2.34E0 is an approximate-value (floating-point) number.
示例:
CREATE TABLE t(A DECIMAL(9,2), B DECIMAL(9,2));
CREATE TABLE r1 AS SELECT SUM(A) / SUM(B) AS result FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r1';
+--------------+---------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+---------------+
| result | decimal(37,6) |
+--------------+---------------+
CREATE TABLE r2 AS SELECT SUM(A) / SUM(B) * 100 AS result FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r2';
+--------------+---------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+---------------+
| result | decimal(40,6) |
+--------------+---------------+
现在使用近似值数字文字100E0
:
CREATE TABLE r3 AS SELECT SUM(A) / SUM(B) * 100E0 AS result FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r3';
+--------------+-------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+-------------+
| result | double |
+--------------+-------------+
值得注意的是,某些操作可能看起来完全相同但 return 不同的数据类型。例如:
CREATE TABLE r4 AS SELECT POWER(A,2) AS result, A*A AS result2 FROM t;
SELECT column_name, column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'r4';
+--------------+---------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+---------------+
| result | double |
| result2 | decimal(18,4) |
+--------------+---------------+
与其讨论计算的细节,不如格式化结果。例如:
SELECT ROUND(100 * sum(...) / sum(...), 1) ...
这给了你小数点后一位的百分比。
当您需要“千位分隔符”(百分比不太可能)时,请参阅 FORMAT()
函数。