私は4つの列を持つテーブルを持っています.これはどのように見えるかです. 私はそれを T_BPR_KPI_MONTHLY_VALUES と呼びます
KPI_NAME_SHORT_S | MONTH_N | YEAR_N | VALUE_N
-----------------------------------------------
MY_KPI_1 | 1 | 2015 | 99.87
MY_KPI_2 | 1 | 2015 | 97.62
... | 1 | 2015 | ...
MY_KPI_1 | 2 | 2015 | ...
... | ... | 2015 | ...
各 KPI は測定値を表し、それぞれに T_BPR_KPI_DY という別のテーブルに保存される毎日の値があります。私の目標は、各 KPI の月ごとの値を計算して保存することです。
特定の日に、一部の KPI の毎日の値がまだ欠落している可能性があります。毎月の値を正確に計算するには、データベース内の既存の値を置き換え、将来の月と年に新しい etry を挿入できる必要があります。
このタスクには、Oracle SQL マージ操作が適していると思いました。アイデアは、エントリが既に存在するかどうかを確認し、存在する場合はその値を更新し、存在しない場合は新しい値を挿入することです。
これはクエリがどのように見えるかです
MERGE INTO T_BPR_KPI_MONTHLY_VALUE A
USING( SELECT 'MY_KPI_1' AS KPI_NAME_SHORT_S, 1 AS MONTH_N, 2014 AS YEAR_N FROM DUAL ) B
ON ( A.KPI_NAME_SHORT_S = B.KPI_NAME_SHORT_S )
WHEN MATCHED THEN
UPDATE SET VALUE_N = ( select AVG(MY_KPI_1) from T_BPR_KPI_DY where DAY_D between '01.01.2014' AND '31.01.2014')
WHEN NOT MATCHED THEN
INSERT (KPI_NAME_SHORT_S, MONTH_N, YEAR_N, VALUE_N) VALUES ('MY_KPI_1', 1, 2014, ( select AVG(MY_KPI_1) from T_BPR_KPI_DY where DAY_D between '01.01.2014' AND '31.01.2014') )
オンザフライで平均月次値を計算することは悪い考えではないと思ったので、ご覧のとおり、特定の kpi の平均月次値のみを計算する別の選択クエリがあります。これが最善の解決策であるかどうかはわかりませんが、このクエリを oracle sql 開発者ツールで実行するとうまくいきます。ただし、アプリから実行しようとすると機能しません。
メソッドはこんな感じ
public static void storeValuesToDb(ArrayList<String> kpiNames) throws SQLException {
Connection conn = getOracleJDBCConnection_DASH();
int currentYear = cal.get(Calendar.YEAR);
int startYear = cal.get(Calendar.YEAR) - 1;
for (String kpiName : kpiNames) {
for (int i = startYear; i <= currentYear; i++) {
for (int j = 0; j < 12; j++) {
try {
String myMergeSQL = ""
+ "MERGE INTO T_BPR_KPI_MONTHLY_VALUE A "
+ "USING( SELECT '" + kpiName + "' AS KPI_NAME_SHORT_S, " + (j + 1) + " AS MONTH_N, " + i + " AS YEAR_N FROM DUAL ) B ON ( A.KPI_NAME_SHORT_S = B.KPI_NAME_SHORT_S ) "
+ "WHEN MATCHED THEN "
+ "UPDATE SET VALUE_N = ( select AVG(" + kpiName + ") from T_BPR_KPI_DY where DAY_D between '" + getFirstDateOfMonth(j, i) + "' AND '" + getLastDateOfMonth(j, i) + "') "
+ "WHEN NOT MATCHED THEN "
+ "INSERT (KPI_NAME_SHORT_S, MONTH_N, YEAR_N, VALUE_N) VALUES ('" + kpiName + "', " + (j + 1) + ", " + i + ", ( select AVG(" + kpiName + ") from T_BPR_KPI_DY where DAY_D between '" + getFirstDateOfMonth(j, i) + "' AND '" + getLastDateOfMonth(j, i) + "') )";
System.out.println(myMergeSQL);
Statement stmt_dash = conn.createStatement();
stmt_dash.executeUpdate(myMergeSQL);
conn.commit();
stmt_dash.close();
} catch (SQLException ex) {
conn.close();
}
}
}
}
conn.close();
}
ターミナルでは、最初のマージ sql のみを出力します。操作を終了することも、例外をスローすることもありません。どういうわけかブロックされ、データベースでも何も起こりません。マージ クエリが正しくないか、ステートメント オブジェクトでこの種の操作を実行できない可能性があります。誰かがこの問題のケースを確認できる場合は、助けてください。
事前にThx