У меня есть таблица MySQL, в которой хранятся данные о ценах некоторых компаний:
| Field | Type | Null | Key | Default | Extra |
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| company_id | int(11) | NO | | NULL | |
| company_name | varchar(200) | YES | | NULL | |
| time_stamp | datetime | YES | | NULL | |
| date | datetime | YES | | NULL | |
| shamsi_date | varchar(12) | YES | | NULL | |
| final_price | decimal(10,3) | YES | | NULL | |
Версия MySQL: 8.0.14
Есть 2048 идентификаторов компаний, а данные о ценахобновляется ежедневно. Я хочу выполнить следующие шаги:
Получить последние N цен каждой компании. N равно 30. Но у некоторых компаний может быть меньше данных, т.е. за 18 дней или 23 дня,
Расчет среднего значения этих цен для каждой компании,
и, наконец, поместите его в другую строку другой таблицы.
Я написал для этого следующий код:
public HashMap<Long, Double> getMeanVolume() {
HashMap<Long, Double> volumeList = new HashMap<Long, Double>();
double sum = 0;
int pageSize = 30;
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<DailyEntity> criteriaQuery = criteriaBuilder.createQuery(DailyEntity.class);
Root<DailyEntity> root = criteriaQuery.from(DailyEntity.class);
criteriaQuery = criteriaQuery.select(root);
// Sorting
criteriaQuery.orderBy(criteriaBuilder.desc(root.get("shamsiDate")));
ArrayList<Long> list = new ArrayList<>();
list = getCompanyID();
for (Long com_id : list) {
sum = 0;
// Selecting
Predicate predicate = criteriaBuilder.equal(root.get("companyID"), com_id);
criteriaQuery.where(predicate);
// Now everything should be gathered together in a TypedQuery:
TypedQuery<DailyEntity> typedQuery = em.createQuery(criteriaQuery);
// Pagination settings
typedQuery.setFirstResult(0);
typedQuery.setMaxResults(pageSize);
// Getting Results. Here as we have Payment as the root element, we have
// can get a list of Payments.
List<DailyEntity> results = typedQuery.getResultList();
if (results.isEmpty())
continue;
for (DailyEntity entit : results) {
sum += entit.getLegal().getNaturalSellVol() + entit.getLegal().getLegalSellVol();
}
volumeList.put(com_id.longValue(), sum / results.size());
log.info(com_id.toString());
}
// volumeList.forEach((key, value) -> {System.out.println(key + " " + value);});
return volumeList;
}
Этот код работает, но оночень медленноРасчет каждого среднего занимает около 0,6 секунд.
Можно ли выполнить этот расчет с некоторыми запросами SQL. Я думаю, что это будет быстрее.
Как я могу улучшить этот код?