У меня есть таблица с четырьмя столбцами, вот как это выглядит. Я бы назвал это 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 все еще отсутствуют, и для точного расчета месячных значений я должен иметь возможность заменить существующие значения в базе данных, а также вставить новые записи для будущих месяцев и лет.
Я думал, что операция слияния 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. Он не завершает операцию и не генерирует исключение. Он каким-то образом блокируется, и в БД тоже ничего не происходит. Возможно, мой запрос на слияние неверен или невозможно выполнить такую операцию с объектом оператора. Если кто-то может увидеть, в каких случаях эта проблема, пожалуйста, помогите.
Спасибо заранее
ex.printStackTrace()
, а также сSystem.err.println(ex.getMessage())
, но ничего не произошло. Я также удалилconn.close()
из блока catch, но это не помогло. однако, когда я выполняю простую вставку sql с этим кодом, он работает нормально. Это тебе что-то говорит? - person amsalk   schedule 18.06.2015select AVG(MY_KPI_1) from T_BPR_KPI_DY where DAY_D between '01.01.2014' AND '31.01.2014'
? - person Bob Jarvis - Reinstate Monica   schedule 18.06.2015