Original Answer
I think I understand what you want. The following assumes you want all attendance dates within a specific range for a specific user. And for each of those attendance dates, you want all cv_target records, if any. And for each of those, you want a count of the candidates.
Use a subquery to get the count. That's the only part that needs to go in the subquery. Only use a GROUP BY
expression in the subquery, not the outer query. Only select the fields you need.
Use LEFT JOIN
to get all the records from the table on the left side of the expression and only matching records from the table on the right side. So all records from attendance (that match the WHERE expression), and matching records from cv_target (regardless of whether they have a match in the candidate subquery), and then matching records from the candidate subquery.
Try this:
SELECT
DATE_FORMAT(a.attendance_date, '%Y-%m-%d') AS attendance_date,
DATE_FORMAT(t.cv_target_date_for, '%Y-%m-%d') AS cv_target_date_for,
t.cv_requirement AS job_id,
t.cv_target,
c.achi AS `achi(count)`
FROM
attendance AS a
LEFT JOIN
cv_target AS t
ON a.fk_user_id = t.cv_recruiter
AND a.attendance_date = t.cv_target_date_for
LEFT JOIN
(
SELECT
COUNT(candidate_id) AS achi,
fk_job_id,
cv_target_date
FROM
candidate
WHERE
fk_posted_user_id = 44
AND cv_target_date BETWEEN '2014-02-01' AND '2014-03-01'
GROUP BY
fk_job_id,
cv_target_date
) AS c
ON t.cv_requirement = c.fk_job_id
AND t.cv_target_date_for = c.cv_target_date
WHERE
a.fk_user_id = 44
AND a.attendance_date BETWEEN '2014-02-01' AND '2014-03-01'
ORDER BY
ISNULL(t.cv_target_date_for), t.cv_target_date_for, t.cv_requirement
Note that the following line is not necessary for the correct result. However, depending on the database structure and amount of data, it may improve performance.
AND cv_target_date BETWEEN '2014-02-01' AND '2014-03-01'
The ISNULL
function is being used to sort NULL
to the bottom.
I've created an SQL Fiddle showing the output you request, except for cv_target_date_for
. It's not possible to output values that do not exist in the data.
UPDATE
With the new data and new requirement of retrieving data where either cv_target or candidate has data for a particular attendance date, you need to add another table to get the job IDs. In your original question you had a table with ID numbers and job titles, but it had no dates.
You might want to rethink your database design. I'm not sure I understand how your tables relate to one another, but those two new records for the candidate table appear to be orphaned. All your joins are based on date, but you don't appear to have a table that links job ID numbers to dates.
You could create a derived table by doing a UNION
of cv_target and candidate. Then use the derived table as the left side of the join.
Updated query:
SELECT
DATE_FORMAT(a.attendance_date, '%Y-%m-%d') AS attendance_date,
DATE_FORMAT(t.cv_target_date_for, '%Y-%m-%d') AS cv_target_date_for,
j.job_id,
t.cv_target,
c.achi AS `achi(count)`
FROM
attendance AS a
LEFT JOIN
(
SELECT
cv_requirement AS job_id,
cv_target_date_for AS job_date
FROM
cv_target
WHERE
cv_recruiter = 44
AND cv_target_date_for BETWEEN '2014-02-01' AND '2014-03-01'
UNION
SELECT
fk_job_id AS job_id,
cv_target_date AS job_date
FROM
candidate
WHERE
fk_posted_user_id = 44
AND cv_target_date BETWEEN '2014-02-01' AND '2014-03-01'
) AS j
ON a.attendance_date = j.job_date
LEFT JOIN
cv_target AS t
ON a.fk_user_id = t.cv_recruiter
AND j.job_id = t.cv_requirement
AND j.job_date = t.cv_target_date_for
LEFT JOIN
(
SELECT
COUNT(candidate_id) AS achi,
fk_job_id,
cv_target_date
FROM
candidate
WHERE
fk_posted_user_id = 44
AND cv_target_date BETWEEN '2014-02-01' AND '2014-03-01'
GROUP BY
fk_job_id,
cv_target_date
) AS c
ON j.job_id = c.fk_job_id
AND j.job_date = c.cv_target_date
WHERE
a.fk_user_id = 44
AND a.attendance_date BETWEEN '2014-02-01' AND '2014-03-01'
ORDER BY
ISNULL(t.cv_target_date_for), t.cv_target_date_for, j.job_id
I've created an updated SQL Fiddle showing the output you request, except for cv_target_date_for
. It's not possible to output values that do not exist in the data (i.e. 2014-02-27).
If that's a typo and you meant 2014-02-28, then you'll need to select the date from the derived table instead of the cv_target table. And you should probably change the column heading in the result because it's no longer the cv_target_date_for
date.
To get the date from either cv_target or candidate, change this line:
DATE_FORMAT(t.cv_target_date_for, '%Y-%m-%d') AS cv_target_date_for,
to this:
DATE_FORMAT(j.job_date, '%Y-%m-%d') AS job_date,
And you may need to tweak the order by expression to suit your needs.