提问人:neucassi 提问时间:10/5/2023 最后编辑:Bill Karwinneucassi 更新时间:10/7/2023 访问量:73
确定 MariaDB 中十进制数据类型列所需的精度和小数位数
Determining required precision and scale for decimal data type columns in MariaDB
问:
我有大量的MariaDB 10.6表,有几列和数百万行。这些列的精度 () 和小数位数 () 曾经被设置为不切实际的高级别,只需容纳每个可能的输入,例如 .decimal(P,D)
P
D
decimal(24,10)
现在,我想根据这些表中的实际数据确定所需的值和值。P
D
我能想到的最好的是
SELECT CEIL(LOG10(MAX(col))) AS maxI,
MAX(CEIL(LOG10(CAST(REVERSE(SUBSTR(CAST(col % 1 AS VARCHAR(12)), 3)) AS INT)))) AS maxD
FROM tbl;
其中是数据类型为、最大整数部分和小数点后最大有效位数的列(so)。col
decimal(24,10)
maxI
maxP
maxP = maxI + maxD
虽然它确实有效,但速度很慢,我想知道是否有更有效的方法可以到达那里。
答:
1赞
Georg Richter
10/5/2023
#1
使用精确数字时,请勿使用双精度函数(如 LOG10),以避免出现警告和舍入错误。
计算小数点前的最大位数非常简单,因为优化器可以在不触及索引的情况下处理。对于无符号小数,您可以使用 ,对于有符号小数,您必须使用 和 :MAX()
MIN()
MAX()
select @maxI1:=LENGTH(TRUNCATE(MIN(col1),0)), @maxI2:=LENGTH(TRUNCATE(MAX(col1),0)) FROM tbl;
最十进制的数字有记录。
所以第二句话是:MAX(col1 - TRUNCATE(col1,0))
SELECT IF(@maxI1 > @maxI2, @maxI1, @maxI2) as maxI,
LENGTH(TRIM(MAX(col1 - TRUNCATE(col1, 0)))+0) -2 as maxD
FROM tbl;
速度比较(7 Mio行):
SELECT CEIL(LOG10(MAX(col1))) AS maxI, MAX(CEIL(LOG10(CAST(REVERSE(SUBSTR(CAST(col1 % 1 AS VARCHAR(12)), 3)) AS INT)))) AS maxD FROM tbl;
+------+------+
| maxI | maxD |
+------+------+
| 13 | 10 |
+------+------+
1 row in set, 40964 warnings (6.166 sec)
与。
SELECT @maxI1:=LENGTH(TRUNCATE(MIN(col1),0)) as maxI1, @maxI2:=LENGTH(TRUNCATE(MAX(col1),0)) as maxI2 FROM tbl;
+-------+-------+
| maxI1 | maxI2 |
+-------+-------+
| 5 | 13 |
+-------+-------+
1 row in set (0.000 sec)
SELECT IF(@maxI1 > @maxI2, @maxI1, @maxI2) as maxI, LENGTH(TRIM(MAX(col1 - TRUNCATE(col1, 0)))+0) -2 as maxD FROM tbl;
+------+------+
| maxI | maxD |
+------+------+
| 13 | 7 |
+------+------+
1 row in set (4.168 sec)
评论
0赞
neucassi
10/6/2023
我得到了完全不同的结果。如果是 5 并且是 13,那么为什么会是 13?不应该是 2 吗?有了你的解决方案,我既没有得到正确的答案,也没有得到 - 总是等于.@maxI1
@maxI2
IF(@maxI1 > @maxI2, LENGTH(@maxI1), LENGTH(@maxI2))
maxI
maxD
maxD
D
0赞
neucassi
10/7/2023
这样就解决了 的问题。但仍然等于列的指定比例。maxI
maxD
D
0赞
Georg Richter
10/7/2023
答案已更新/更正。
0赞
neucassi
10/7/2023
MAX(value - TRUNCATE(value, 0)
给我们一个没有整数部分的最大值(例如 0.65),而我们应该找到“最长”的值(0.21746)。我同意@Barmar的观点,即没有办法绕过字符串。
评论
CEIL(LOG10(MAX(col)))
col
LOG10
maxD
REGEXP_REPLACE