How to query employee details and relate their performance metrics?
There is actually no need to create the additional depth/complexity just to hold the count data. Furthermore, by using a combination of LEFT JOINs to connect the related tables and apply your required conditional rules, you can achieve your desired result by making just one trip to the database. This will without question provide superior efficiency for your application. LEFT JOINs are important to use so that counts can be zero without excluding employees from the result set.
Also, I should point out that your attempted query was mistakenly comparing a MONTH()
value against a DATE()
value -- that was never going to end well. :) In fact, to ensure that your sql is accurately isolating the current month from the current year, you need to be also checking the YEAR value.
My recommended sql:
SELECT employees.id, employees.firstname, employees.lastname, COUNT(DISTINCT leads.c_id) AS leadsThisMonth, SUM(IF(fileStatus.f_filestatus = 1, 1, 0)) AS disbursedThisMonth, SUM(IF(fileStatus.f_filestatus = 2, 1, 0)) AS filesubmitThisMonthFROM tbl_employee AS employeesLEFT JOIN tbl_lead AS leads ON employees.id = leads.createdby AND leadstatus = 1 AND MONTH(leads.date_of_created) = MONTH(CURRENT_DATE()) AND YEAR(leads.date_of_created) = YEAR(CURRENT_DATE()) LEFT JOIN tbl_bankdata AS bankData ON employees.id = bankData.createdbyLEFT JOIN tbl_fileStatus AS fileStatus ON bankData.bank_id = fileStatus.f_bankid AND MONTH(fileStatus.date_of_created) = MONTH(CURRENT_DATE()) AND YEAR(fileStatus.date_of_created) = YEAR(CURRENT_DATE()) AND fileStatus.f_id = ( SELECT MAX(subFileStatus.f_id) FROM tbl_fileStatus AS subFileStatus WHERE subFileStatus.f_bankid = bankData.bank_id GROUP BY subFileStatus.f_bankid )WHERE employees.is_archive = 0 AND employees.is_approved = 1GROUP BY employees.id, employees.firstname, employees.lastname
The SUM(IF())
expression is a technique used to execute a "conditional count". "Aggregate data" is formed by using GROUP BY and there are specialized "aggregate functions" which must be used to create linear/flat data from these clusters/non-flat collections of data. fileStatus
data is effectively piled up upon itself due to the GROUP BY call. If COUNT(fileStatus.f_filestatus)
was called, it would count all of the rows in the cluster. Since you wish to differentiate between f_filestatus = 1
and f_filestatus = 2
, an IF()
statement is used. This is doing the same thing as COUNT()
(adding 1 for every qualifying occurrence), but it is different from COUNT()
in that it does not count specific rows (within the scope of the cluster) unless the IF()
expression is satisfied. Another example.
Here is a db fiddle demo with some adjustments to your supplied sample data: https://www.db-fiddle.com/f/8MoWmKPuzTrrC3DQJsiX35/4 (The result set will only be "good" while the current is June of this year.)
After saving the above string as $sql
, you can simply execute it and loop through the array of objects like this:
foreach ($this->db->query($sql)->result() as $object) { // these are the properties available in each object // $object->id // $object->firstname // $object->lastname // $object->leadsThisMonth // $object->disbursedThisMonth // $object->filesubmitThisMonth}