First of all, apologies if this is a duplicate, I don't really know the best terminology for this question.
Say I have SQL schema that represents:
Businesses:
id: int
name: string
Employees:
id: int
business_id: int REFERENCES Businesses(id)
name: string
Is there any conceivable way I could query for a list of businesses each with an array of employees attached as a field? Currently I am pulling the list of businesses into my server, and then for each business in the array, getting all employees who have a business_id equal to its id. This works, but for a large number of businesses, it results in a high number of queries to the database.
Another option I considered was reading all employees into memory on my server, putting them into a map of [business_id->[employees]]
, and then sending the employees array to the right businesses employees
field on the server. This seems to be a much more performant option, but I wanted to know if there is anything built into MySQL that would allow me to do this out of the box, as it seems like a pretty common task. Thank you!
EDIT: @MatBailie made a point about code smells here, and I just wanted to clarify the total intent of this code. I will add a step by step walkthrough of what it would do from a high level.
- Select all companies from a list
- Get all employees of each company
- Display to a user a list of companies, and next to each one, a scrollable list of each employee
I understand, as @radocaw pointed out, that getting a list of employees for a business is a trivial join, but my issue is that this will take numerous trips to the database. I will post my current method of solving this issue in Golang below, using two simple SELECTs from MySQL and the use of maps. This is for you, @Tangentially Perpendicular!
employeeMap := make(map[int][]Employee)
employees,err := db.Query("SELECT business_id,f_name,l_name,email FROM employees")
if err != nil {
//handle error
}
for employees.Next(){
var employee Employee
err = employees.Scan(&employee.BusinessId,&employee.FName,&employee.LName,&employee.Email)
if err != nil {
//handle error
continue
}
if _,ok := employeeMap[employee.BusinessId];ok{
employeeMap[employee.BusinessId] = append(employeeMap[employee.BusinessId],employee)
}else {
employeeMap[employee.BusinessId] = make([]Employee,1)
employeeMap[employee.BusinessId[0] = employee
}
}
This is used to build a map of business ids to lists of employees. Next I would just get the businesses from the database, and for their id, attach that array of employees to them.
I'm not sure if this is even a good way to do this, but it seems more optimized and direct than hitting the database with n joins, where n is the number of businesses. Thanks everyone for the great feedback and high quality answers/comments!