How to query employee details and relate their performance metrics?

后端 未结 1 881
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-21 08:06

I am fetching the id, first name, and last name of all employees that are approved and not archived. Then I am looping these results and using the ids to query other tables

相关标签:
1条回答
  • 2020-12-21 08:43

    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 filesubmitThisMonth
    FROM tbl_employee AS employees
    
    LEFT 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.createdby
    
    LEFT 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 = 1
    
    GROUP 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
    }
    
    0 讨论(0)
提交回复
热议问题