タイプNumericの金額フィールドを持つテーブルがあります。異なる金額値が含まれています。例えば
5.00
7.13
8.86
6.00
1.00
...など
小数点以下がゼロ以外のレコードのみをフェッチする必要があります。つまり、金額に対応するレコードのみを取得します
7.13
8.86
どうすればいいですか?
タイプNumericの金額フィールドを持つテーブルがあります。異なる金額値が含まれています。例えば
5.00
7.13
8.86
6.00
1.00
...など
小数点以下がゼロ以外のレコードのみをフェッチする必要があります。つまり、金額に対応するレコードのみを取得します
7.13
8.86
どうすればいいですか?
numeric
正確です!別の回答で主張されているのとは異なり、浮動小数点型numeric
ではなく、SQL 標準で定義されている任意精度型です。保管は正確です。マニュアルを引用します:
数値型は、桁数が非常に多い数値を格納し、正確に計算を実行できます。正確さが要求される金額やその他の数量を格納する場合に特にお勧めします。
あなたの質問の自然な候補は functiontrunc()
です。ゼロに向かって切り捨てます- 基本的に整数部分を保持し、残りを破棄します。簡単なテストでは最速ですが、上位候補の間ではその差はわずかです。
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 でテスト済み。numeric
小数部が 2 桁の10,000 の数字を含む一時テーブルで、約 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 ミリ秒
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 倍以上速くなりました)。10k ではなく 100k 行でテストします。
デシベル<>ここでフィドル
これはうまくいきます:
SELECT *
FROM t
WHERE round(amount,2) != round(amount)
いいえ、浮動小数点数を直接比較することはできません-以下のコードは機能しません(証明としてSQLFiddle ):
SELECT *
FROM t
WHERE amount != round(amount)
amount
=の場合1./3 * 3
、 のように見えますが1
、そうではありません - 比較は失敗します。
これは役に立ちますか
SELECT * FROM table WHERE amount - floor(amount) > .00
SELECT *
FROM t
WHERE amount != round(amount);