【发布时间】:2015-06-18 07:53:41
【问题描述】:
我有一个四列的表格,这就是它的样子。我会称之为 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 代表一个测量值,每个 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。它既不完成操作也不抛出异常。它以某种方式阻塞,并且在数据库中也没有发生任何事情。我的合并查询可能不正确,或者无法使用语句对象执行这种操作。如果有人能够看到这个问题是什么情况,请提供帮助。
提前谢谢
【问题讨论】:
-
你的 catch(SQLException ex) 只是关闭了连接。在控制台上打印异常消息,它将包含错误。
-
嗨,谢谢重播。我已经按照您对
ex.printStackTrace()和System.err.println(ex.getMessage())的建议进行了尝试,但没有任何反应。我还从 catch 块中删除了conn.close(),但它没有帮助。但是,当我使用此代码执行简单的插入 sql 时,它工作正常。这说明你什么了吗? -
select AVG(MY_KPI_1) from T_BPR_KPI_DY where DAY_D between '01.01.2014' AND '31.01.2014'执行需要多长时间?