我有一个表格,其中的金额字段类型为Numeric。它包含不同的金额值。例如
5.00
7.13
8.86
6.00
1.00
...等等
我必须只获取那些小数点后非零的记录。 即只取金额对应的记录
7.13
8.86
我该怎么做?
最佳答案
numeric
是准确的!
与另一个答案声称的不同,numeric
是 not a floating-point type ,而是一个 arbitrary precision type由 SQL 标准定义。存储准确。我引用手册:
The type numeric can store numbers with a very large number of digits and perform calculations exactly. It is especially recommended for storing monetary amounts and other quantities where exactness is required.
回答
您的问题的自然候选者是函数 trunc()
.它将截断为零 - 基本上保留整数部分而丢弃其余部分。在快速测试中最快,但在顶级竞争者之间差异不大。
SELECT * FROM t WHERE amount <> trunc(amount);
floor()
截断到下一个较小的整数,这与负数有区别:
SELECT * FROM t WHERE amount <> floor(amount);
如果您的数字符合 integer
/ bigint
你也可以投:
SELECT * FROM t WHERE amount <> amount::bigint;
这四舍五入到完整数字,与上面不同。
测试
使用 PostgreSQL 9.1.7 测试。包含 10k 个 numeric
数字和两个小数位的临时表,大约 1% 有 .00
。
CREATE TEMP TABLE t(amount) AS
SELECT round((random() * generate_series (1,10000))::numeric, 2);
在我的案例中,正确的结果是:9890 行。使用 EXPLAIN ANALYZE
运行 10 次的最佳时间。
欧文 1
SELECT count(*) FROM t WHERE amount <> trunc(amount) -- 43.129 ms
SELECT count(*) FROM t WHERE amount != round(amount) -- 43.406 ms
欧文 3
SELECT count(*) FROM t WHERE amount <> amount::int -- 43.668 ms
SELECT count(*) FROM t WHERE round(amount,2) != round(amount) -- 44.144 ms
欧文 4
SELECT count(*) FROM t WHERE amount <> amount::bigint -- 44.149 ms
欧文 2
SELECT count(*) FROM t WHERE amount <> floor(amount) -- 44.918 ms
SELECT count(*) FROM t WHERE amount - floor(amount) > .00 -- 46.640 ms
在 Postgres 12 中大部分仍然正确(除了现在一切都快了 > 10 倍)。使用 100k 行而不是 10k 行进行测试:
db<> fiddle here
关于sql - 获取 PostgreSQL 中小数点后非零的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15240652/