亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

關于java對查詢結果進行環比指標計算的代碼示例

關于java對查詢結果進行環比指標計算的代碼示例

收到一只叮咚 2019-02-16 23:08:20
需求想要統計環比指標((本期數量-上期數量)/上期數量*100%) 假設下面是統計9月份的數據 如下所示 品牌 數量 環比 Bosh 1561 311.87% Siemens 2278 -75.24% 問題查詢的時候 需要同時查詢8月的數據 統計出8月的數量 然后才能進行環比指標的計算 { "count" : 379.0, "brand" : "Bosch", "month" : "2017-08" } { "count" : 1561.0, "brand" : "Bosch", "month" : "2017-09" } { "count" : 9202.0, "brand" : "Siemens", "month" : "2017-08" } { "count" : 2278.0, "brand" : "Siemens", "month" : "2017-09" } 怎么轉換得到上圖的結果呢? 即 { "count" : 379.0, "brand" : "Bosch", "month" : "2017-08" } { "count" : 1561.0, "brand" : "Bosch", "month" : "2017-09" } { "count" : 9202.0, "brand" : "Siemens", "month" : "2017-08" } { "count" : 2278.0, "brand" : "Siemens", "month" : "2017-09" } ==> { "count" : 1561.0, "brand" : "Bosch", "month" : "2017-09","huanbi": 311.87 } { "count" : 2278.0, "brand" : "Siemens", "month" : "2017-09","huanbi":-75.24 } 我以為挺好實現的 沒想到還挺折騰的 代碼如下 Map<String,Object> record1 = new HashMap(ImmutableMap.of("count", 379, "brand", "Bosch", "month", "2017-08")); Map<String,Object> record2 = new HashMap(ImmutableMap.of("count", 1561, "brand", "Bosch", "month", "2017-09")); Map<String,Object> record3 = new HashMap(ImmutableMap.of("count", 9202, "brand", "Siemens", "month", "2017-08")); Map<String,Object> record4 = new HashMap(ImmutableMap.of("count", 2278, "brand", "Siemens", "month", "2017-09")); Map<String,Object> record5 = new HashMap(ImmutableMap.of("count", 2278, "brand", "foo", "month", "2017-09")); List<Map<String, Object>> queryResult = Lists.newArrayList(record1, record4, record3, record2, record5); // 先按品牌和日期排序 queryResult.sort((o1,o2)->{ int result = 0; String[] keys = {"brand", "month"}; for (String key : keys) { String val1 = o1.get(key).toString(); String val2 = o2.get(key).toString(); result = val1.compareTo(val2); if(result != 0){ return result; } } return result; }); // 再按品牌分組 Map<String, List<Map<String, Object>>> brand2ListMap = queryResult.stream().collect(groupingBy(m -> m.get("brand").toString(), toList())); /** * 每組中第一條肯定是上一月的 找到上月的數目 * 第二條記錄是本月的 找到本月的數據 * 計算環比 本期記錄中添加環比 * 同時刪除上一條記錄 */ for (String key : brand2ListMap.keySet()) { List<Map<String, Object>> recordList = brand2ListMap.get(key); if (recordList.size() > 1) { Map<String, Object> prevRecord = recordList.get(0); Map<String, Object> currentRecord = recordList.get(1); Integer prevCount = (Integer) prevRecord.get("count"); Integer currentCount = (Integer) currentRecord.get("count"); BigDecimal huanbi = BigDecimal.valueOf((currentCount - prevCount) * 100).divide(BigDecimal.valueOf(prevCount), 2, ROUND_HALF_DOWN); currentRecord.put("huanbi", huanbi); recordList.remove(0); }else{ // 不存在上期記錄 環比默認為0 recordList.get(0).put("huanbi", 0); } } // 生成一個新的List 只包含本期記錄 List<Map<String, Object>> processedResult = new ArrayList(brand2ListMap.values().stream().flatMap(list->list.stream()).collect(toList())); // 按照品牌排序 processedResult.sort(Comparator.comparing(o -> o.get("brand").toString())); processedResult.forEach(System.out::println); 輸出結果如下 {count=1561, month=2017-09, brand=Bosch, huanbi=311.87} {count=2278, month=2017-09, brand=Siemens, huanbi=-75.24} {count=2278, month=2017-09, brand=foo, huanbi=0} 應該不是我想的復雜了吧?應該沒有更簡單的方案了吧?
查看完整描述

3 回答

?
慕工程0101907

TA貢獻1887條經驗 獲得超5個贊

剛剛看到你的私信。如果用MongoDB解決的話方法如下:

// 測試數據
db.test.insert([
    { "count" : 379.0, "brand" : "Bosch", "month" : "2017-08" },
    { "count" : 1561.0, "brand" : "Bosch", "month" : "2017-09" },
    { "count" : 9202.0, "brand" : "Siemens", "month" : "2017-08" },
    { "count" : 2278.0, "brand" : "Siemens", "month" : "2017-09" }
]);
// 運算方法
db.test.aggregate([
    {$match: {month: {$in: ["2017-08", "2017-09"]}}},
    {$sort: {month: 1}},
    {$group: {_id: "$brand", lastMonth: {$first: "$count"}, thisMonth: {$last: "$count"}, month: {$last: "$month"}}},
    {$project: {brand: 1, ratio: {$divide: [{$subtract: ["$thisMonth", "$lastMonth"]}, "$lastMonth"]}}}
])
// 結果
{ "_id" : "Siemens", "ratio" : -0.7524451206259509 }
{ "_id" : "Bosch", "ratio" : 3.1187335092348283 }

為了最好的效果,需要添加一些索引以優化查詢:

db.test.createIndex({month: 1});

另外建議你日期都用Date,不要用字符串,這是個良好的習慣。就算現在用起來沒什么區別,早晚也是會需要它是個日期的。

查看完整回答
反對 回復 2019-03-01
?
ITMISS

TA貢獻1871條經驗 獲得超8個贊

這個很適合java8的stream。

查看完整回答
反對 回復 2019-03-01
  • 3 回答
  • 0 關注
  • 1242 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號