質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1477閲覧

java からSQLクエリを実行して取得した結果と、DBアプリ上で直にクエリを実行した結果が異なる

20200812_javaer

総合スコア11

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/04/09 06:46

編集2021/04/09 06:48

お世話になります。

==
SELECT
ROUND(AVG( 基準日終値*( CASE 基準年月
WHEN '202012' THEN 1 WHEN '202011' THEN 1 WHEN '202010' THEN 0.25
END )),2,1) AS 最小終値
FROM ~
==

java(Servlet)で、上記のクエリで平均値を取得すると、
74.39 が返ります。このときgetBigDecimalで値を取得しています。
上記のクエリをDB(SQL Server Management Studio )上で直に実行すると、
74.40が返ります。また、Excelで計算すると、やはり74.40が返ります。

何故、javaの場合、74.39が返るのでしょうか?
getBigDecimalで値を取得していますが、これを
getStringやgetDoubleに変更しても結果は同じでした。

ちなみに、平均値を算出する値は以下の通りです。
77.15
75.91
75.33
75.49
74.98
74.33
74.71
74.4
74.51
75.06
74.44
74.91
73.55
73.8
73.28
73.67
73.68
73.27
72.52
73.35
74.31
74.15

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

SQLServerには詳しくありません。あしからず。

引数
...
length numeric_expression を丸める際の有効桁数です。
function 実行する操作の種類です。 ... 0 以外の値を指定した場合、... は切り捨てられます。

件のSQL。

sql

1SELECT ROUND(AVG(基準日終値*...),2,1)

functionには1を渡しています。lengthで「切り捨て」ですね。

基準日終値の型がなんだかわかりませんが、件のデータをdoubleで計算すると、74.39999999999999です。切り捨てれば74.39

何故、javaの場合、74.39が返るのでしょうか?

74.39999999999999を、切り捨てて74.39

上記のクエリをDB(SQL Server Management Studio )上で直に実行すると、74.40が返ります。

round関数の定義をみると、むしろ、この結果のほうが疑わしいのではないかと。


kotlin

1import org.junit.jupiter.api.Test 2import java.math.BigDecimal 3 4class HogeAvg { 5 @Test 6 fun aa() { 7 val values: List<String> = data.trim().split("""\s+""".toRegex()) 8 println(values) 9 10 val doubleAverage = values.map { it.toDouble() }.average() 11 println("doubleAverage: ${doubleAverage}") 12 // doubleAverage: 74.39999999999999 13 14 val bigDecimalAverage = 15 values 16 .map { it.toBigDecimal() } 17 .fold(BigDecimal.ZERO) { a, b -> a + b } / values.size.toBigDecimal() 18 println("bigDecimalAverage: ${bigDecimalAverage}") 19 // bigDecimalAverage: 74.40 20 } 21 22 val data = """ 2377.15 2475.91 2575.33 2675.49 2774.98 2874.33 2974.71 3074.4 3174.51 3275.06 3374.44 3474.91 3573.55 3673.8 3773.28 3873.67 3973.68 4073.27 4172.52 4273.35 4374.31 4474.15 45 """.trimIndent() 46}

投稿2021/04/10 13:18

shiketa

総合スコア4061

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

20200812_javaer

2021/04/12 01:43

>shiketa様 ご回答頂きまして、有難うございます。 以下の点、補足させて頂きます。 SQLServerに登録されている「基準日終値」の型は、decimal(16, 6)です。 DB(SQL Server Management Studio )上に直接クエリを記載し、 試しにROUNDせずに、AVG(基準日終値)だけで実行しても、74.4000000が返りました。 実際のPGでは、javaでは計算せずに、 ResultSet rs = stmt.executeQuery() でクエリを実行して、 rs.getBigDecimal でこの結果を変数に格納するだけなのですが、 変数には74.40が格納されます。 rs.getDouble、rs.getStringでも同じ結果です。 もう少し、私の方でも調査してみます。
guest

0

ベストアンサー

SQLServerには詳しくありません。あしからず。

float型というのがあるんですね。
基準日終値の型 decimal(16, 6) と float だけのテーブルをつくってためしてみました。
create table test (decValue decimal(16,6), floatValue float)
結果。

select avg(decValue) as _dec_avg, round(avg(decValue),2,1) as _dec_round, avg(floatValue) as _float_avg, round(avg(floatValue),2,1) as _float_round from test avg: [(_dec_avg, 74.400000), (_dec_round, 74.400000), (_float_avg, 74.39999999999999), (_float_round, 74.39)]

件のSQLは、こう。

sql

1ROUND( 2 AVG(基準日終値 3 * ( 4 CASE 基準年月 5 WHEN '202012' THEN 1 6 WHEN '202011' THEN 1 7 WHEN '202010' THEN 0.25 8 END 9 ) 10 ) 11 ,2,1) AS 最小終値

基準年月が202010のとき、0.25 を掛けてます。この結果として、最小終値がfloat型になっているのではないでしょうか。

kotlin

1import java.sql.DriverManager 2 3object HogeTest { 4 @JvmStatic 5 fun main(args: Array<String>) { 6 val url = "jdbc:sqlserver://localhost" 7 val conn = DriverManager.getConnection(url, "sa", "password@12345") 8 println("conn: ${conn}") 9 10 conn.createStatement().let { st -> 11 val sql = """drop table if exists test""" 12 println(sql) 13 st.execute(sql) 14 st.close() 15 } 16 17 conn.createStatement().let { st -> 18 val sql = """create table test (decValue decimal(16,6), floatValue float)""" 19 println(sql) 20 st.execute(sql) 21 st.close() 22 } 23 24 """insert into test values(?, ?)""".let { sql -> 25 println(sql) 26 conn.prepareStatement(sql).let { st -> 27 dataList.trim().split("""\s+""".toRegex()) 28 .forEach { data -> 29 st.setBigDecimal(1, data.toBigDecimal()) 30 st.setBigDecimal(2, data.toBigDecimal()) 31 st.execute() 32 } 33 st.close() 34 } 35 } 36 37 conn.createStatement().let { st -> 38 val sql = """select * from test""" 39 println(sql) 40 st.executeQuery(sql).let { rs -> 41 while (rs.next()) { 42 val row = (1..rs.metaData.columnCount).map { index -> 43 rs.metaData.getColumnName(index) to rs.getString(index) 44 } 45 println("row: ${row}") 46 } 47 rs.close() 48 } 49 st.close() 50 } 51 52 println("----") 53 54 conn.createStatement().let { st -> 55 val sql = """ 56 select 57 avg(decValue) as _dec_avg, 58 round(avg(decValue),2,1) as _dec_round, 59 avg(floatValue) as _float_avg, 60 round(avg(floatValue),2,1) as _float_round 61 from test""".trimIndent() 62 println(sql) 63 st.executeQuery(sql).let { rs -> 64 while (rs.next()) { 65 val row = (1..rs.metaData.columnCount).map { index -> 66 rs.metaData.getColumnName(index) to rs.getBigDecimal(index) 67 } 68 println("avg: ${row}") 69 } 70 rs.close() 71 } 72 st.close() 73 } 74 75 } 76 77 val dataList = """ 7877.15 7975.91 8075.33 8175.49 8274.98 8374.33 8474.71 8574.4 8674.51 8775.06 8874.44 8974.91 9073.55 9173.8 9273.28 9373.67 9473.68 9573.27 9672.52 9773.35 9874.31 9974.15 100 """.trimIndent() 101}
conn: ConnectionID:1 ClientConnectionId: 6e2f8d13-0f16-4b7c-a773-7444fb6d5d3d drop table if exists test create table test (decValue decimal(16,6), floatValue float) insert into test values(?, ?) select * from test row: [(decValue, 77.150000), (floatValue, 77.15)] row: [(decValue, 75.910000), (floatValue, 75.91)] row: [(decValue, 75.330000), (floatValue, 75.33)] row: [(decValue, 75.490000), (floatValue, 75.49)] row: [(decValue, 74.980000), (floatValue, 74.98)] row: [(decValue, 74.330000), (floatValue, 74.33)] row: [(decValue, 74.710000), (floatValue, 74.71)] row: [(decValue, 74.400000), (floatValue, 74.4)] row: [(decValue, 74.510000), (floatValue, 74.51)] row: [(decValue, 75.060000), (floatValue, 75.06)] row: [(decValue, 74.440000), (floatValue, 74.44)] row: [(decValue, 74.910000), (floatValue, 74.91)] row: [(decValue, 73.550000), (floatValue, 73.55)] row: [(decValue, 73.800000), (floatValue, 73.8)] row: [(decValue, 73.280000), (floatValue, 73.28)] row: [(decValue, 73.670000), (floatValue, 73.67)] row: [(decValue, 73.680000), (floatValue, 73.68)] row: [(decValue, 73.270000), (floatValue, 73.27)] row: [(decValue, 72.520000), (floatValue, 72.52)] row: [(decValue, 73.350000), (floatValue, 73.35)] row: [(decValue, 74.310000), (floatValue, 74.31)] row: [(decValue, 74.150000), (floatValue, 74.15)] ---- select avg(decValue) as _dec_avg, round(avg(decValue),2,1) as _dec_round, avg(floatValue) as _float_avg, round(avg(floatValue),2,1) as _float_round from test avg: [(_dec_avg, 74.400000), (_dec_round, 74.400000), (_float_avg, 74.39999999999999), (_float_round, 74.39)]

最後に。DBeaverで件のDB接続した結果はこうなりました。おもいきり不審ですネ。

select avg(decValue) as _dec_avg, round(avg(decValue),2,1) as _dec_round, avg(floatValue) as _float_avg, round(avg(floatValue),2,1) as _float_round from test ; 表示された検索結果 74.400000 74.400000 74.40 74.39 コピペした検索結果 74.400000 74.400000 74.39999999999999 74.39

どんなツールでSQLの実行結果を確認されたのかしりませんが、そのツールで表示されている結果は、見えている結果は、ホントウの値なのでしょうか?すくなくともDBeaverのデフォルト設定では、そうではないみたいです。

投稿2021/04/13 01:32

shiketa

総合スコア4061

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

20200812_javaer

2021/04/13 01:51

>shiketa様 何度もご検証頂きまして、有難うございます。 大変、参考になりました。 >そのツールで表示されている結果は、見えている結果は、ホントウの値なのでしょうか 確かに、仰る通りですね。 私の方でも、もう少し調査と、これらの勉強をしていきます。 本当に、有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問