0

I have completely no idea how to translate this sql query into Java Streams using the Speedment Framework. The “result table” in Java could be of any type (it could be Map or even a specially defined user class).

Here’s the sql query I’m trying to translate into Java Streams:

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;

DB Scheme which I'm using
Source: https://github.com/datacharmer/test_db/tree/master/images

Thanks in advance.

KMR
  • 792
  • 13
  • 21
arealek
  • 1
  • 2

1 Answers1

0

Thanks to the Speedment channel on Youtube I have found a solution.

1) Create a “Result/Wrapper” class for aggregation:

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) Create a join object:

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) Create rules for aggregation:

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) Create an aggregation object:

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

5) Do whatever you have to do with it:

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

Output:

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'}
arealek
  • 1
  • 2