11

我有一个带有Numeric类型的数量字段的表。它包含不同的金额值。例如

5.00
7.13
8.86
6.00
1.00

... ETC。

我必须只获取小数点后非零的那些记录。即,仅获取与金额对应的记录

7.13
8.86

我该怎么做?

4

4 回答 4

17

numeric是准确的!

与另一个答案所声称的不同,numeric不是浮点类型,而是SQL 标准定义的任意精度类型。存储准确。我引用手册:

numeric 类型可以存储具有非常多位数的数字并精确地执行计算。特别推荐用于存储货币数量和其他需要精确性的数量。

回答

您问题的自然候选者是 function 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 测试。有 10knumeric个数字和两个小数位的临时表,大约 1% 有.00.

CREATE TEMP TABLE t(amount) AS
SELECT round((random() * generate_series (1,10000))::numeric, 2);

在我的情况下正确的结果:9890 行。10 次运行的最佳时间EXPLAIN ANALYZE

欧文 1

SELECT count(*) FROM t WHERE amount <> trunc(amount) -- 43.129 ms

MVP 2 / QQ

SELECT count(*) FROM t WHERE amount != round(amount)          -- 43.406 ms

欧文 3

SELECT count(*) FROM t WHERE amount <> amount::int            -- 43.668 ms

MVP 1

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<>在这里摆弄

于 2013-03-08T00:03:13.850 回答
3

这将起作用:

SELECT *
FROM t
WHERE round(amount,2) != round(amount)

不,您不能直接比较浮点数- 下面的代码不起作用(SQLFiddle作为证明):

SELECT *
FROM t
WHERE amount != round(amount)

如果amount= 1./3 * 3,它看起来像1,但它不是 - 比较将失败。

于 2013-03-06T07:12:30.590 回答
3

这有帮助吗

SELECT * FROM table WHERE amount - floor(amount) > .00

于 2013-03-06T07:38:37.687 回答
2
SELECT *
FROM t
WHERE amount != round(amount);
于 2013-03-06T06:47:52.463 回答