- PR -

【MySQL】 浮動小数点数フィールドに関して

1
投稿者投稿内容
リング
会議室デビュー日: 2008/05/27
投稿数: 10
投稿日時: 2008-05-27 15:50
お世話になっております。

現在MySQL5.0を使用して、とある業務系のシステムを開発しております。

現在DBのテーブルは以下のようになっております。
-----------------------------------------------------------------
テーブル名:TableA

id(integer) data(float) memo(varchar)
1       1.1      メモ1
2       2.2      メモ2
-----------------------------------------------------------------

上記のテーブルに対して、次のSQLを実行致しました。
-----------------------------------------------------------------
SELECT * FROM tableA WHERE data >= 1.1 And data <=2.2;
-----------------------------------------------------------------
実行結果としては、id=1のレコードのみが取得されました。

なぜid=2のレコードが取得されないか疑問に思い調べたところ、dataの
値が近似値に丸められているため、実際は、2.20000004みたいな感じで
格納されているという事が分かりました。
(float型に"="で条件を指定できない事も把握済みです。)

そこで、float型に対して、範囲検索を行いたいのですが、どのように
すれば可能でしょうか?

また、dataに格納されるデータに関しては、整数部の桁数、小数点以下
の桁数、共に可変であり、決まった桁数ではありません。ただし、小数
点を含め9桁で構成されることのみ決まっております。

どなたかご存じであれば、アドバイスをお願い致します。


[ メッセージ編集済み 編集者: リング 編集日時 2008-05-27 15:51 ]

[ メッセージ編集済み 編集者: リング 編集日時 2008-05-27 15:52 ]
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2008-05-27 16:39
floatじゃなくてNumericかDecimal使えば良いんじゃないの?

または、非標準の表記法として、float(M, D)ってのもあるらしい。

詳細は以下のリンク先をどうぞ
10.2. Numeric Types(mysql.com)
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2008-05-27 16:50
追記:
もし、テーブル定義を変更できないのなら、キャストするしかないかも
コード:

SELECT * FROM tableA WHERE cast(data as decimal(2, 2)) >= 1.1 And cast(data as decimal(2, 2)) <=2.2



未確認だから、動かなくても怒らないでね



[ メッセージ編集済み 編集者: かずくん 編集日時 2008-05-27 16:51 ]
リング
会議室デビュー日: 2008/05/27
投稿数: 10
投稿日時: 2008-05-27 17:42
かずくん様、貴重なご意見ありがとうございます。

まず、テーブル定義を変更するという対応に関してですが、
今回テーブル定義を変えるとなると、既存のプログラムの
修正が大変という事もあり、Numric/Decimal化に関しては
最後の手段として考えてさせて頂きます。

次に、decimalへのキャストに関しては、早速試させて頂き
ました。

-----------------------------------------------------------------
テーブル名:TableA

id(integer) data(float) memo(varchar)
1       1.1      メモ1
2       2.2      メモ2
3       3.3      メモ3
4       4.4      メモ4
5       5.555     メモ5
6       66.66     メモ6
-----------------------------------------------------------------
-----------------------------------------------------------------
SELECT * FROM tableA WHERE cast(data as decimal(16, 7)) >= 1.1
And cast(data as decimal(16, 7)) <= 4.4
-----------------------------------------------------------------

実行結果としては、id=1,2,3が取得でき、id=4は取得できませんでした。
原因としては、4.4は実際4.4000001となっているようで、条件に引っか
からないのだと思います。

ちなみに(data as decimal(16, 7))は、

・整数だけの9桁
・整数1桁と小数7桁
・整数2桁と小数6桁
・整数3桁と小数5桁
・整数4桁と小数4桁
・整数5桁と小数3桁
・整数6桁と小数2桁
・整数7桁と小数1桁

を想定しています。

検索条件も1.1や2.2だけでなく、上記パターンのものがセットされること
も想定しなくてはなりません。

やはりそういう意味では、Numric/Decimalへテーブル定義を変更する方向
を考えなくてはなりませんでしょうか?
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2008-05-27 21:39
逆にfloatにキャストするってのは、もうやった?
コード:
SELECT * FROM tableA WHERE data >= cast(1.1 as float) And data <= cast(2.2 as float); 

ina
ベテラン
会議室デビュー日: 2005/04/14
投稿数: 58
投稿日時: 2008-05-27 22:27
この問題(近似値)はSQLに限らないので、カラムの属性変えちゃった方が後々のメンテナンスが楽だと思いますが....
※既にリリースされているアプリで使われていると考えちゃいますが...
リング
会議室デビュー日: 2008/05/27
投稿数: 10
投稿日時: 2008-05-28 09:00
かずくん様、ina様、ご意見誠にありがとうございます。

まず、floatにキャストする件ですが、castのtypeにfloat
が存在しないため、エラーになる模様です。
http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html

カラム属性を変える件ですが、確かにSQLだけでなく、
アプリ側でもこの問題は残る可能性があります。
ただ、おっしゃっておられますように既にリリース
されているアプリの改造で、あまり工数をかけられ
ない状況です。少しでも現行版に影響のない方法を
と思い調査しておりました。

お二人の意見を元に、この辺でDecimal/Numricへ
変更する方向に切り替えたいと思います。

貴重なご意見、誠にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)