简体   繁体   中英

MySql query and GROUP BY, what do I need to do differently?

Right now I have an sql query that selects a range of of my sales reps, then joins a customer table, and counts if certain values are true. My query works, however, It leaves out sales reps who have not sold any customers. I would like this query to return all sales reps, even if they have not created any client records matching the criteria. What do I need to change?

Here is a link to my SQL Query: http://pastie.org/4557540 (same as below)

SELECT u.id                                                           AS
       `employee_id`,
       u.`first_name`                                                 AS
       `employee_first_name`,
       u.`last_name`                                                  AS
       `employee_last_name`,
       (SELECT Count(*)
        FROM   saleset s
        WHERE  s.pitchedby_id = `employee_id`
               AND s.pitchstartedat BETWEEN '2012-08-20 00:00:00' AND
                                            '2012-08-20 23:59:59')    AS
       `transfers_taken`,
       Count(IF(c.`saletype_id` IS NOT NULL, 1, NULL))                AS
       `total_closes`,
       Count(IF(c.`saletype_id` = 1, 1, NULL))                        AS
       `regular_sale`,
       Count(IF(c.`saletype_id` = 2, 1, NULL))                        AS
       `postdated_sale`,
       Count(IF(c.`saletype_id` = 4, 1, NULL))                        AS
       `attempted_sale`,
       Count(IF(c.`customerstatus_id` IN ( 8, 18, 23 ), 1, NULL))     AS
       `cancel_status`,
       Count(IF(c.`customerstatus_id` IN ( 1, 12, 13, 24 ), 1, NULL)) AS
       `pending_completion_status`,
       Count(IF(c.`customerstatus_id` IN ( 5, 6, 16 ), 1, NULL))      AS
       `complete_status`,
       Count(IF(c.`customerstatus_id` = 20, 1, NULL))                 AS
       `postdate_pending`,
       Count(IF(c.`customerstatus_id` = 25, 1, NULL))                 AS
       `postdate_declined`
FROM   `user` u
       LEFT JOIN customer c
              ON c.`salesrep_id` = u.id
WHERE  u.id IN ( 39, 65, 76, 96,
                 195, 266, 349, 401,
                 402, 404, 405, 407,
                 411, 412 )
       AND c.`activationdate` BETWEEN
           '2012-08-20 00:00:00' AND '2012-08-20 23:59:59'
GROUP  BY u.`id`

The problem is that your are filtering the customers in the WHERE clause, after the LEFT JOIN is specified, so salesman with no sales get left out, because c.activationdate is null for these records.

The solution is having the client filtering inside the join conditions:

(...)
FROM   `user` u
       LEFT JOIN customer c
              ON (c.`salesrep_id` = u.id and
                  u.id IN ( 39, 65, 76, 96, 195, 266, 349, 401,
                            402, 404, 405, 407,
                            411, 412 ) 
                  AND c.`activationdate` BETWEEN
                      '2012-08-20 00:00:00' AND '2012-08-20 23:59:59')

GROUP  BY u.`id`

Perhaps you could take what you have an union it with your sales reps that have no sales, and just hard code them to 0. Something like:

SELECT u.id                                                           AS 
       `employee_id`, 
       u.`first_name`                                                 AS 
       `employee_first_name`, 
       u.`last_name`                                                  AS 
       `employee_last_name`, 
       (SELECT Count(*) 
        FROM   saleset s 
        WHERE  s.pitchedby_id = `employee_id` 
               AND s.pitchstartedat BETWEEN '2012-08-20 00:00:00' AND 
                                            '2012-08-20 23:59:59')    AS 
       `transfers_taken`, 
       Count(IF(c.`saletype_id` IS NOT NULL, 1, NULL))                AS 
       `total_closes`, 
       Count(IF(c.`saletype_id` = 1, 1, NULL))                        AS 
       `regular_sale`, 
       Count(IF(c.`saletype_id` = 2, 1, NULL))                        AS 
       `postdated_sale`, 
       Count(IF(c.`saletype_id` = 4, 1, NULL))                        AS 
       `attempted_sale`, 
       Count(IF(c.`customerstatus_id` IN ( 8, 18, 23 ), 1, NULL))     AS 
       `cancel_status`, 
       Count(IF(c.`customerstatus_id` IN ( 1, 12, 13, 24 ), 1, NULL)) AS 
       `pending_completion_status`, 
       Count(IF(c.`customerstatus_id` IN ( 5, 6, 16 ), 1, NULL))      AS 
       `complete_status`, 
       Count(IF(c.`customerstatus_id` = 20, 1, NULL))                 AS 
       `postdate_pending`, 
       Count(IF(c.`customerstatus_id` = 25, 1, NULL))                 AS 
       `postdate_declined` 
FROM   `user` u 
       INNER JOIN customer c 
              ON c.`salesrep_id` = u.id 
WHERE  u.id IN ( 39, 65, 76, 96, 
                 195, 266, 349, 401, 
                 402, 404, 405, 407, 
                 411, 412 ) 
       AND c.`activationdate` BETWEEN 
           '2012-08-20 00:00:00' AND '2012-08-20 23:59:59' 
GROUP  BY u.`id`
UNION
SELECT u.id                                                           AS 
       `employee_id`, 
       u.`first_name`                                                 AS 
       `employee_first_name`, 
       u.`last_name`                                                  AS 
       `employee_last_name`, 
       0                                                              AS 
       `transfers_taken`, 
       Count(IF(c.`saletype_id` IS NOT NULL, 1, NULL))                AS 
       `total_closes`, 
       Count(IF(c.`saletype_id` = 1, 1, NULL))                        AS 
       `regular_sale`, 
       Count(IF(c.`saletype_id` = 2, 1, NULL))                        AS 
       `postdated_sale`, 
       Count(IF(c.`saletype_id` = 4, 1, NULL))                        AS 
       `attempted_sale`, 
       Count(IF(c.`customerstatus_id` IN ( 8, 18, 23 ), 1, NULL))     AS 
       `cancel_status`, 
       Count(IF(c.`customerstatus_id` IN ( 1, 12, 13, 24 ), 1, NULL)) AS 
       `pending_completion_status`, 
       Count(IF(c.`customerstatus_id` IN ( 5, 6, 16 ), 1, NULL))      AS 
       `complete_status`, 
       Count(IF(c.`customerstatus_id` = 20, 1, NULL))                 AS 
       `postdate_pending`, 
       Count(IF(c.`customerstatus_id` = 25, 1, NULL))                 AS 
       `postdate_declined` 
FROM   `user` u 
       LEFT JOIN customer c 
              ON c.`salesrep_id` = u.id 
WHERE  u.id IN ( 39, 65, 76, 96, 
                 195, 266, 349, 401, 
                 402, 404, 405, 407, 
                 411, 412 ) 
       AND c.`activationdate` BETWEEN 
           '2012-08-20 00:00:00' AND '2012-08-20 23:59:59'
       AND c.`salesrep_id` IS NULL 
GROUP  BY u.`id`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM