我对 SQL 还很陌生,我觉得我让这件事变得比实际需要的更加困难。希望有人能指出我正确的方向。
目标是返回一组可用用户,这些用户被分配到我们正在处理的站点,并且可以执行我们想要分配的任务。
对于这个问题,我们可以假设我们正在处理 site_id 4 并且我们正在尝试分配 task_id 2。
我们的桌子是:
Table: site_tasks_assignments
id | user_id | site_id | task_id | complete
--------------------------------------------
12 | 6 | 4 | 2 | 1
13 | 4 | 3 | 2 | 0
14 | 2 | 4 | 3 | 0
15 | 6 | 4 | 4 | 1
Table: users
id | name | site_id
-----------------------
1 | bob | 1
2 | henry | 4
3 | jane | 2
4 | mary | 3
5 | kyle | 4
6 | steve | 4
如果满足以下条件,用户应出现在结果中:
users.site_id
= 我们正在工作的站点的 ID(再次假设 site_id
4)并且,以下任意一项为真:
users.id
根本没有出现在site_task_assignments.user_id
中,这意味着他们在任何站点都没有被分配任何任务,site_task_assignments
表中,但 尚未被分配该特定任务(在本例中为 task_id
2),site_task_assignments
表中并且 已 被分配了该特定任务并且该行的 site_task_assignments.complete
列为 1考虑到上述参数,我期望的结果是:
id | name | site_id
-----------------------
2 | henry | 4 <- not assigned to task 2, can work on site 4
5 | kyle | 4 <- not assigned to any tasks, can work on site 4
6 | steve | 4 <- WAS assigned to task 2, task 2 complete, can do task 2 again, can work on site 4
我尝试了几个版本的查询,其中一些涉及某种 JOIN,还有一些涉及子查询等。我得到的最接近的是:
SELECT u.*, sta.task_id, sta.user_id, sta.complete FROM users as u
LEFT JOIN site_task_assignments as ci ON u.id = sta.user_id
WHERE u.site_id = 4
AND (u.id NOT IN (SELECT user_id FROM site_task_assignments)
OR (u.id IN (SELECT user_id FROM site_task_assignments) AND sta.task_id = 2 AND complete = 1)
OR (u.id IN (SELECT user_id FROM site_task_assignments) AND (sta.task_id = 2 AND complete = 1 OR sta.task_id != 2 AND complete = 0)))
这给了我不一致的结果。在某些任务上,这很好,在已分配的其他任务上,它有时会向我提供用户已分配给任务但完成度为 0 的信息。在根本未分配的任务上,它会向我提供重复的任务如果他们已经在其他任务的
site_task_assignments
表中,则为同一用户。
试试这个:
select distinct u.id as id,name, u.site_id as site_id
from users u
left join site_tasks_assignments s
on u.id=s.user_id
where u.site_id=4 and (s.user_id is null
or not exists (select 1 from site_tasks_assignments
where site_tasks_assignments.user_id=s.user_id and site_tasks_assignments.task_id =2)
or exists (select 1 from site_tasks_assignments
where site_tasks_assignments.user_id=s.user_id and site_tasks_assignments.task_id =2 and complete=1)
)
;