计算表的最后N条记录的平均值

时间:2019-11-02 18:37:50

标签: hibernate jpa spring-data-jpa

我有一个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个公司ID,并且定价数据每天更新。我要执行以下步骤:

  1. 获取每个公司的最后N个价格。 N为30。但是某些公司的数据可能较少,即18天或23天,

  2. 计算每个公司的平均价格,

  3. 并最终将其放在另一个表的另一行中。

我已经编写了以下代码:

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秒。

  1. 是否可以通过某些SQL查询执行此计算。我认为它将更快。

  2. 如何改进此代码?

1 个答案:

答案 0 :(得分:0)

尝试这种方式 在您的存储库中

@Query("SELECT AVG(final_price)  FROM (SELECT final_price FROM companies ORDER BY company_id DESC LIMIT ?1)")
Double getAverageOfLastNRecords(int n);