誰かがVARCHAR2(256 CHAR)として列を作成し、この列に数字しかない場合はどうなりますか。一番多い番号を取得したいのですが。問題は次のとおりです。数値は999999を超えていますが、varcharの最大値は常に999999の最大数を示しています。
私は試しto_number(max(numbers), '9999999999999')
ましたが、それでも999999が返されますが、それはできません。何か案は?ありがとうございました
最善の方法は
最初のソリューション は、列を数値に変換します
また
2番目の解決策 は、クエリのデータを数値で変換し、データを取得するよりも...
例
select max(col1) from(
select to_number(numbers) as col1 from table ) d
TO_NUMBER() の前に MAX() を呼び出すと、アルファベット順に並べ替えられ、999999 が 100000000000 よりも大きくなるため、このようにする必要があります。varchar2 列に TO_NUMBER() を適用すると、INVALID_NUMBER 例外が発生するリスクがあることに注意してください。数字以外の文字を含む列。これが、最初に提案されたソリューションが優先される理由です。
Oracle では、NUMBER 型には 100 を底とする浮動小数点値が含まれ、有効桁数は 38 桁で、最大値は 9999...(38 個の 9) x 10^125 です。2 つの問題があります。1 つ目は、256 文字の文字列から変換された値を NUMBER に含めることができるかどうか、2 つ目は、数値的に「近い」2 つの値を区別できるかどうかです。
256 文字の文字列を数値に変換することから始めましょう。やるべきことは明らかです:
SELECT TO_NUMBER('9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999') AS VAL
FROM DUAL;
上記を実行すると、次のようになります。
ORA-01426: numeric overflow
これは、以前に注意を払っていたので、予想していました。NUMBER が処理できる最大の指数は 125 です。ここでは、有効数字 256 桁の値を変換しようとしています。NUMBER ではこれを処理できません。桁数を 125 に減らすと、次のようになります。
SELECT TO_NUMBER('99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999') AS VAL
FROM DUAL;
それは問題なく動作し、私たちの答えは 1E125 です。
<点滅>
うわあ!待つ!!何???答えは1 ×10^125??? それらすべての 9 はどうですか?!?!?!?
Oracle NUMBER は、最大精度が 38 で最大指数が 125 の浮動小数点値であることを前に説明したことを思い出してください。 (覚えておいてください、最大精度は 38 です (これについては後で詳しく説明します))。したがって、それはできる限り最善を尽くします-最初の38桁(すべて9です)を変換し、「結果A)入力の代表とB)をできるだけ近づけるために、これをどのように丸めるのが最善ですか」と言います私が与えられたものを手に入れることができますか?」. この場合、数字の 39 を見て、それが 9 であることを確認し、切り上げを決定します。残りの桁もすべて 9 なので、残りの仮数桁が 1 になるまできれいに丸められます。
* その後、牧場に戻ります... *
先ほど、NUMBER の精度は 38 桁であると述べました。これは完全に正しいわけではありません。風が正しく、下り坂にある場合は、実際には最大 40 桁の精度で値を区別できます。次に例を示します。
SELECT CASE
WHEN to_number('9999999999999999999999999999999999999999') >
to_number('9999999999999999999999999999999999999998')
THEN 'Greater'
ELSE 'Not greater'
END AS VAL
FROM DUAL;
これらの 2 つの値はそれぞれ 40 桁です (カウントは非常に退屈な読者のための演習として残されています :-)。上記を実行すると、2 つの 40 桁の値の比較が成功したことを示す'Greater'が返されます。
今、いくつかの楽しみのために。各文字列にさらに '9' を追加して 41 桁の値を作成し、ステートメントを再実行すると、'Not greater' が返されます。
<点滅>
待つ!何??うわあ!!!価値観が明らかに違う!TotalFool (tm) でさえそれを見ることができます!!
ここでの問題は、41 桁の数値が NUMBER 型の精度を超えていることです。したがって、TO_NUMBER がこれほど長い値を持つことを検出すると、右側の桁を破棄し始めます。したがって、これらの 2 つの非常に大きな数は、あなたと私にとっては明らかに異なっていても、折りたたまれ、紡錘体で切断され、切断され、変換された後では、まったく違いはありません。
では、ここでの要点は何ですか?
1-OPの元の質問に対して-OracleのNUMBER型は256桁の値を保持できないため、NUMBERを使用する以外に数値文字列を比較する別の方法を考え出す必要があります。すべての値が 256 桁の長さであることを確認して文字列を正規化し、必要に応じて左側にゼロを追加すると、文字列の比較が正常に機能するはずです。
2 - 浮動小数点数は、(あなたの好きな悪の擬人化) の作品であるため、否定によって (あなたの好きな神々) の存在を証明します。彼らと一緒に仕事をするときはいつでも(遅かれ早かれ誰もがそうしなければならないので)、彼らが悪意のある悪の悪い副産物であり、思いがけないときにあなたを攻撃するのを待っていることを覚えておく必要があります.
3 -ポイント 3はありません。(そして、頭蓋外の検索エンジンに頼らずに識別できる人には追加のクレジットがあります :-)
共有してお楽しみください。
列の数値がそれほど大きくなる可能性がある場合 (256 桁)、次のように試すことができます。
SELECT numbers
FROM (
SELECT numbers
FROM table_name
ORDER BY LPAD(numbers, 256) DESC
)
WHERE rownum = 1
またはこのように:
SELECT LTRIM(MAX(LPAD(numbers, 256))) AS numbers
FROM table_name