我有三张桌子:出勤率,cv_target和候选人。我需要找到特定用户的候选人数。
我不是MySQL的专家。我已经尝试了下面的查询,但我无法找到确切的值。
SELECT
attendance_date,
cv_target_date_for,
cv_requirement,
job_id,
cv_target,
achi,
recruiter_comment,
recruiter_rating
FROM
attendance f
RIGHT JOIN
(
SELECT
cv_requirement,
cv_target,
cv_target_date_for,
achi,
recruiter_comment,
recruiter_rating
FROM
cv_target a
LEFT JOIN
(
SELECT
COUNT(candidate_id) AS achi,
cv_target_date,
fk_job_id
FROM
candidate
GROUP BY
fk_job_id,
cv_target_date
) b
ON a.cv_requirement = b.fk_job_id
AND a.cv_target_date_for = b.cv_target_date
WHERE
cv_target_date_for BETWEEN '2014-02-01' AND '2014-03-01'
AND cv_recruiter = '36'
) c
ON f.attendance_date=c.cv_target_date_for
GROUP BY
cv_requirement,
cv_target_date_for
ORDER BY
c`.`cv_target_date_for` ASC
出勤
id fk_user_id attendance_date
1 44 2014-02-24
2 44 2014-02-25
3 44 2014-02-26
4 44 2014-02-27
5 36 2014-02-24
6 44 2014-02-28
cv_target
id cv_recruiter cv_requirement cv_target cv_target_date_for
1 44 1 3 2014-02-24
2 44 2 2 2014-02-24
3 44 3 2 2014-02-25
4 44 4 3 2014-02-25
4 44 4 3 2014-02-26
候选人
candidate_id fk_posted_user_id fk_job_id cv_target_date
1 44 1 2014-02-24
2 44 3 2014-02-25
3 44 3 2014-02-25
3 44 4 2014-02-25
4 44 4 2014-02-26
5 44 5 2014-02-28
5 44 5 2014-02-28
期望的结果
attendance_date cv_target_date_for job_id cv_target achi(count)
2014-02-24 2014-02-24 1 3 1
2014-02-24 2014-02-24 2 2 null
2014-02-25 2014-02-25 3 2 2
2014-02-25 2014-02-25 4 3 1
2014-02-26 2014-02-26 4 3 1
2014-02-27 2014-02-27 null null null
2014-02-28 null 5 null 2
我得到的输出
attendance_date cv_target_date_for job_id cv_target achi(count)
2014-02-24 2014-02-24 1 3 1
2014-02-24 2014-02-24 2 2 null
2014-02-25 2014-02-25 3 2 2
2014-02-25 2014-02-25 4 3 1
2014-02-26 2014-02-26 4 3 1
日期27和28未显示。我也想要那些价值观。
答案 0 :(得分:1)
我想我明白你想要什么。以下假设您希望特定用户的特定范围内的所有出勤日期。对于每个出勤日期,您需要所有cv_target记录(如果有)。对于每一个,你想要一个候选人的数量。
使用子查询来获取计数。这是子查询中唯一需要进入的部分。仅在子查询中使用GROUP BY
表达式,不外部查询。只选择您需要的字段。
使用LEFT JOIN
从表达式左侧的表中获取所有记录,并仅匹配右侧表中的记录。所以来自出勤的所有记录(与WHERE表达式匹配),以及来自cv_target的匹配记录(无论它们是否在候选子查询中都匹配),然后匹配候选子查询中的记录。
试试这个:
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
请注意,正确的结果不需要以下行。但是,根据数据库结构和数据量,它可能会提高性能。
AND cv_target_date BETWEEN '2014-02-01' AND '2014-03-01'
ISNULL
函数用于将NULL
排序到底部。
我创建了一个显示您请求的输出的SQL Fiddle,cv_target_date_for
除外。无法输出数据中不存在的值。
使用新数据和检索数据的新要求 cv_target 或 候选人拥有数据特殊的出勤日期,您需要添加另一个表来获取作业ID。在您的原始问题中,您有一张带有身份证号码和职位的表格,但它没有日期。
您可能想重新考虑数据库设计。我不确定我是否了解您的表格如何相互关联,但候选表格的这两个新记录似乎是孤立的。您的所有联接都基于日期,但您似乎没有将作业ID号与日期相关联的表。
您可以通过执行UNION
cv_target和候选来创建派生表。然后使用派生表作为连接的左侧。
更新了查询:
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
我创建了一个更新的SQL Fiddle,显示了您请求的输出,cv_target_date_for
除外。无法输出数据中不存在的值(即 2014-02-27 )。
如果这是一个拼写错误并且您的意思是 2014-02-28 ,那么您需要从派生表而不是cv_target表中选择日期。您应该更改结果中的列标题,因为它不再是cv_target_date_for
日期。
要从 cv_target 或候选人那里获取日期,请更改此行:
DATE_FORMAT(t.cv_target_date_for, '%Y-%m-%d') AS cv_target_date_for,
到此:
DATE_FORMAT(j.job_date, '%Y-%m-%d') AS job_date,
您可能需要通过表达式调整订单以满足您的需求。