我的情况有点难以描述。我将尝试用一个例子和我想要的结果来解释。
我有三张桌子
Employee
| id | Name |
|----+-------|
| 1 | Alice |
| 2 | Bob |
| 3 | Jane |
| 4 | Jack |
Task
| id | employee_id | description |
|----+-------------+---------------------|
| 1 | 1 | Fix bug |
| 2 | 1 | Implement feature |
| 3 | 1 | Deploy master |
| 4 | 2 | Integrate feature |
| 5 | 2 | Fix cosmetic issues |
Status
| id | task_id | time | details | Terminal |
|----+---------+-------+-----------+----------|
| 1 | 1 | 12:00 | Assigned | false |
| 2 | 1 | 12:30 | Started | false |
| 3 | 1 | 13:00 | Completed | true |
| 4 | 2 | 12:10 | Assigned | false |
| 5 | 2 | 14:00 | Started | false |
| 6 | 3 | 12:15 | Assigned | false |
| 7 | 4 | 12:20 | Assigned | false |
| 8 | 5 | 12:25 | Assigned | false |
| 9 | 4 | 12:30 | Started | false |
(我还将这些内容放在http://sqlfiddle.com/#!9/728c85/1)
的sqlfiddle页面中基本思想是我有一些员工和任务。这些任务可以分配给员工,当他们处理这些任务时,他们会不断添加" status"行。
每个状态条目都有一个字段" terminal"这可能是真的也可能是假的。
如果某个任务的最后一个状态条目的终端设置为true,那么该任务结束,并且无需再进行任何操作。
如果分配给员工的所有任务都已结束,则该员工将被视为免费。
我需要获得一份免费员工名单。在给定员工的情况下,这基本上意味着他们所有具有状态的任务列表。所以,像Alice这样的事情
| Task | Completed |
|-------------------+-----------|
| Fix bug | true |
| Implement feature | false |
| Deploy master | false |
我从中知道她现在不是免费的,因为有错误的'完成的条目。
我该怎么做?如果我的表格不适合这种查询,我也非常喜欢这方面的建议。
(因为我想按每个用户订购每个任务的状态,然后将它们限制在最后一行,我将这个问题命名为这样的问题。)
有人告诉我,status
字段应该真正进入任务表,而Status表应该简单地是一个日志表。
答案 0 :(得分:3)
我会想把这个状态放在任务表中。 (请参阅我对此请求的评论。)但是,这里有两个选择免费员工的问题:
如果无法重新打开任务,则很简单:通过检查是否存在terminal = true的记录来获取所有未完成的任务。免费员工都没有完成任务。
select *
from employee
where id not in
(
select employee_id
from task
where id not in (select task_id from status where terminal = true)
);
但是,如果可以重新打开任务,那么您可以执行相同操作,但必须找到最后一个状态。这可以通过Postgre的DISTINCT ON
来完成。
select *
from employee
where id not in
(
select employee_id
from task
where not
(
select distinct on (task_id) terminal
from status
where task_id = task.id
order by task_id, id desc
)
);
(我使用ID来查找每个任务的最后一个条目,因为没有日期的时间似乎不合适。如果任务总是只在一天内运行,则只能使用时间列。)
SQL fiddles:
答案 1 :(得分:0)
您必须将所有状态分组为gheter,然后您可以使用MAX()
查找其中一个是否为真,如下所示:
SELECT t.description, MAX(s.terminal)
FROM Employee e
INNER JOIN task t ON t.employee_id = e.id
INNER JOIN status s ON s.task_id = t.id
GROUP BY t.id;
如果您希望仅为一位用户添加此类内容WHERE e.id = 1
。
答案 2 :(得分:0)
我希望这能帮到你...... ??
select E.Name,T.id as[Task Id],T.description,S.Terminal from Employee E
inner join Task T on E.id=T.employee_id
inner join Status S on S.task_id=T.id
where e.id not in (select employee_id from Task where id in (select task_id from Status where Terminal='true' and details='Completed') )
答案 3 :(得分:0)
希望这有帮助
select T.employee_id, T.description, S.Terminal
from Employee E
INNER JOIN Task T ON E.id=T.employee_id
INNER JOIN (Select task_id, max(id) as status_id FROM Status GROUP BY task_id) as ST on T.id=ST.task_id
INNER JOIN Status S on S.id=ST.status_id