- Because the job_post table (suboptimally) stores city data as a comma-separate string, your query cannot reliably use
IN() to filter the records. Fortunately, the joined city table offers city_id as a normalized INT type column.
- I am a little confused about the
is_delete = 1 in this query. The truthy value logically indicates to me that the intention is to return rows which ARE deleted, but that would be unlikely to be a common/useful query. If the column is meant to indicate "active" records, then the column name should probably be name is_active where 1 means active and 0 means not active.
- It is a bad practice, for performance and maintenance reasons, to store comma-separated values in a database. You should rethink and refactor your database and codebase to store atomic values. Research First Normal Form (1NF).
I took some creative liberties while testing/experimenting with your query and some fabricated data, but below should still contain all of the valuable data and logic from your query. PHPize Demo (without verbose quoting)
To cover cases when $cities is an empty array, prevent and empty IN() expression in your rendered query by writing ?: null. CodeIgniter's query builder class will not add the condition to the SQL if where_in()'s array parameter is null.
public function getJobPosts(int $userId, array $cities = []): array
{
return $this->db
->select([
'p.job_id',
'p.emp_id',
vsprintf('MAX(%s) %s', $this->db->escape_identifiers(['i.industry_name', 'industry_name'])),
'p.role role_id',
vsprintf('GROUP_CONTACT(DISTINCT %s) %s', $this->db->escape_identifiers(['c.name', 'found_city_name_list'])),
vsprintf('GROUP_CONTACT(DISTINCT %s) %s', $this->db->escape_identifiers(['s.skill', 'skill_name_list'])),
vsprintf('MAX(%s) %s', $this->db->escape_identifiers(['u.first_name', 'first_name'])),
vsprintf('MAX(%s) %s', $this->db->escape_identifiers(['u.last_name', 'last_name'])),
vsprintf('COALESCE(MAX(%s), 0) %s', $this->db->escape_identifiers(['f.is_favourite', 'is_favourite'])),
])
->from('job_post p')
->join('users u', 'p.emp_id = u.user_id')
->join('industry i', 'p.industry_id = i.ind_id', 'left')
->join(
'city c',
vsprintf(
'FIND_IN_SET(%s, %s)',
$this->db->escape_identifiers(['c.city_id', 'p.city'])
),
'left',
false
)
->join(
'skill s',
vsprintf(
'FIND_IN_SET(%s, %s)',
$this->db->escape_identifiers(['s.skill_id', 'p.skill'])
),
'left',
false
)
->join(
'user_favourite_job f',
'p.job_id = f.job_id AND f.user_id = ' . $this->db->escape($userId),
'left'
)
->where_in('c.city_id', $cities ?: null)
->where('p.is_delete', 1)
->group_by('p.job_id')
->get()
->result();
}
The fully quoted SQL will render as:
SELECT `p`.`job_id`, `p`.`emp_id`, MAX(`i`.`industry_name`) `industry_name`, `p`.`role` `role_id`, GROUP_CONTACT(DISTINCT `c`.`name`) `found_city_name_list`, GROUP_CONTACT(DISTINCT `s`.`skill`) `skill_name_list`, MAX(`u`.`first_name`) `first_name`, MAX(`u`.`last_name`) `last_name`, COALESCE(MAX(`f`.`is_favourite`), 0) `is_favourite`
FROM `job_post` `p`
JOIN `users` `u` ON `p`.`emp_id` = `u`.`user_id`
LEFT JOIN `industry` `i` ON `p`.`industry_id` = `i`.`ind_id`
LEFT JOIN city c ON FIND_IN_SET(`c`.`city_id`, `p`.`city`)
LEFT JOIN skill s ON FIND_IN_SET(`s`.`skill_id`, `p`.`skill`)
LEFT JOIN `user_favourite_job` `f` ON `p`.`job_id` = `f`.`job_id` AND `f`.`user_id` = 8
WHERE `p`.`is_delete` = 1
GROUP BY `p`.`job_id`