Функция агрегации в таблице результатов, состоящей из данных из нескольких таблиц с использованием Speedment - PullRequest
0 голосов
/ 28 ноября 2018

Я совершенно не представляю, как перевести этот SQL-запрос в потоки Java с помощью Speedment Framework.«Таблица результатов» в Java может быть любого типа (это может быть Map или даже специально определенный пользовательский класс).

Вот запрос sql, который я пытаюсь перевести в потоки Java:

SELECT d.dept_name, AVG(s.salary)
FROM employees e
JOIN salaries s
ON e.emp_no=s.emp_no
JOIN dept_emp de ON de.emp_no = e.emp_no
JOIN  departments d ON d.dept_no=de.dept_no
WHERE s.to_date = '9999-01-01' AND de.to_date = '9999-01-01'
GROUP BY d.dept_name;

Схема БД, которую я использую Источник: https://github.com/datacharmer/test_db/tree/master/images

Заранее спасибо.

1 Ответ

0 голосов
/ 30 ноября 2018

Благодаря каналу Speedment на Youtube я нашел решение.

1) Создайте класс «Result / Wrapper» для агрегации:

private static class Result {
        private Double salary;
        private String departmentName;

        public Double getSalary() { return salary; }
        public void setSalary(Double salary) { this.salary = salary; }
        public String getDepartmentName() { return departmentName; }
        public void setDepartmentName(String departmentName) {
            this.departmentName = departmentName;
        }

        @Override
        public String toString() {
            return "Result{" +
                    "salary=" + salary +
                    ", departmentName='" + departmentName + '\'' +
                    '}';
        }
    }

2) Создайте объект объединения:

Join<Tuple2<Departments, Salaries>> join = app.getOrThrow(JoinComponent.class)
                .from(EmployeesManager.IDENTIFIER)
                .innerJoinOn(DeptEmp.EMP_NO).equal(Employees.EMP_NO)
                    .where(DeptEmp.TO_DATE.equal(Date.valueOf("9999-01-01")))
                .innerJoinOn(Departments.DEPT_NO).equal(DeptEmp.DEPT_NO)
                .innerJoinOn(Salaries.EMP_NO).equal(Employees.EMP_NO)
                    .where(Salaries.TO_DATE.equal(Date.valueOf("9999-01-01")))
                .build((a,b,c,d) -> Tuples.of(c,d));

3) Создайте правила агрегации:

AggregationCollector<Tuple2<Departments, Salaries>, ?, Result> aggregationCollector = Aggregator.builder(Result::new)
                            .firstOn(Tuple2.<Departments, Salaries>getter0())
                                .andThen(Departments.DEPT_NAME)
                                .key(Result::setDepartmentName)
                            .firstOn(Tuple2.getter1())
                                .andThen(Salaries.SALARY)
                                .average(Result::setSalary)
                            .build()
                            .createCollector();

4) Создайте объект агрегации:

Aggregation<Result> aggregation = join.stream().collect(aggregationCollector);

5) Делайте все, что нужнос ним:

aggregation.streamAndClose().forEachOrdered(System.out::println);

Вывод:

Result{salary=67657.91955820487, departmentName='Development'}
Result{salary=78559.93696229013, departmentName='Finance'}
Result{salary=67843.30198484214, departmentName='Production'}
Result{salary=80058.84880743832, departmentName='Marketing'}
Result{salary=63921.89982943111, departmentName='Human Resources'}
Result{salary=88852.96947030538, departmentName='Sales'}
Result{salary=67285.23017815467, departmentName='Customer Service'}
Result{salary=67913.3749757136, departmentName='Research'}
Result{salary=65441.99340024768, departmentName='Quality Management'}
...