SQL查询帮助 - 任务排序,分组和状态+日期条件问题

时间:2008-10-29 23:12:27

标签: sql oracle

希望我能解决问题的正义,因为在标题中总结它太难了! (评论中欢迎提出建议)

是的,所以这是我的表:

Tasks
  task_id        (number)
  job_id         (number)
  to_do_by_date  (date)
  task_name      (varchar / text)
  status         (number)
  completed_date (date)

为了论证,让我们创建状态值:

1 = New
2 = InProgress
3 = Done

我正在尝试做的事情是创建一个可以回退所有任务的查询:

  • job_id的任何任务都有status<>完成
    • 除了job_id的所有任务都已完成,但一个或多个任务今天有completed_date的情况
  • to_be_done_by日期排序,但将所有job_id任务分组在一起
    • 所以首先显示带有下一个`to_do_by_date'任务的job_id

有关数据的一些信息:

  • job_id可以有任意数量的任务


以下是我想要获得的输出示例:

task_id   job_id   to_do_by_date   task_name   status   completed_date
   1        1        yesterday        -          3        yesterday
   2        1        today            -          3        today
   3        2        now              -          3        today
   4        2        2 hours time     -          2        {null}
   5        2        4 hours time     -          2        {null}
   6        2        tomorrow         -          1        {null}
   7        3        3 hours time     -          2        {null}
   8        3        tomorrow         -          1        {null}
   9        3        tomorrow         -          1        {null}


我正在使用Oracle 10g,所以Oracle或ANSI SQL的答案,或者如何处理这个问题的提示都是理想的,我可以创建视图或将其包装在存储过程中,以便在您的解决方案需要时从应用程序中卸载逻辑它


这是一个sql脚本,它将创建上面显示的示例测试数据:

create table tasks (task_id number, job_id number, to_do_by_date date, task_name varchar2(50), status number, completed_date date);
insert into tasks values (0,0,sysdate -2,    'Job 0, Task 1 - dont return!', 3, sysdate -2);
insert into tasks values (1,1,sysdate -1,    'Job 1, Task 1', 3, sysdate -1);
insert into tasks values (2,1,sysdate -2/24, 'Job 1, Task 2', 3, sysdate -2/24);
insert into tasks values (3,2,sysdate,       'Job 2, Task 1', 3, sysdate);
insert into tasks values (4,2,sysdate +2/24, 'Job 2, Task 2', 2, null);
insert into tasks values (5,2,sysdate +4/24, 'Job 2, Task 3', 2, null);
insert into tasks values (6,2,sysdate +1,    'Job 2, Task 4', 1, null);
insert into tasks values (7,3,sysdate +3/24, 'Job 3, Task 1', 2, null);
insert into tasks values (8,3,sysdate +1,    'Job 3, Task 2', 1, null);
insert into tasks values (9,3,sysdate +1,    'Job 3, Task 3', 1, null);
commit;


很多,非常感谢你的帮助:o)

4 个答案:

答案 0 :(得分:2)

显然你需要解决这个问题,但我希望你明白这一点。

SELECT 
    task_id, job_id, to_do_by_date, task_name, status, completed_date
FROM
    Tasks
WHERE
    job_id IN (
        SELECT job_id 
        FROM Tasks 
        WHERE status <> 'Done' 
        GROUP BY job_id)
    OR
    job_id IN (
        SELECT job_id 
        FROM Tasks 
        WHERE status = 'Done' AND completed_date = 'Today'
            AND job_id NOT IN (SELECT job_id FROM Tasks WHERE status <> 'Done' GROUP BY job_id)
        GROUP BY job_id)
ORDER BY
    job_id, to_do_by_date

答案 1 :(得分:2)

我同意贾斯汀的说法 - 我不明白为什么要回归2。

这是一个使用分析函数根据逻辑描述返回正确行的查询。

select * from
(
select t.*,
       min(status) over (partition by job_id) min_status_over_job,
       max(status) over (partition by job_id) max_status_over_job,
       sum(case when trunc(completed_date) = trunc(sysdate)-1 then 1 else 0 end) 
                   over (partition by job_id) num_complete_yest
from   tasks t
)
where  max_status_over_job < 3
       or (min_status_over_job = 3 and num_complete_yest > 0)
/

答案 2 :(得分:0)

鉴于您的要求,我不清楚为什么应该在结果中返回job_id 2。有一个状态为Done的任务,因此它未通过第一个标准

  

job_id的所有任务都有   状态&lt;&gt;完成

并且有些任务的状态不是Done,因此它没有达到第二个标准

  

除了job_id的所有任务   已完成,但一项或多项任务   有一个今天的completed_date

还有其他原因应该包括job_id = 2吗?

SQL> ed
Wrote file afiedt.buf

  1  select task_id, job_id, to_do_by_date, task_name, status, completed_date
  2    from tasks t1
  3   where not exists( select 1
  4                       from tasks t2
  5                      where t1.job_id = t2.job_id
  6                        and t2.status  = 3)
  7      or ((not exists( select 1
  8                        from tasks t3
  9                       where t1.job_id  = t3.job_id
 10                         and t3.status != 3))
 11          and
 12          exists (select 1
 13                    from tasks t4
 14                   where t1.job_id = t4.job_id
 15                     and trunc(t4.completed_date) = trunc(sysdate)))
 16*   order by job_id, to_do_by_date
SQL> /

   TASK_ID     JOB_ID TO_DO_BY_ TASK_NAME           STATUS COMPLETED
---------- ---------- --------- --------------- ---------- ---------
         1          1 28-OCT-08 Job 1, Task 1            3 28-OCT-08
         2          1 29-OCT-08 Job 1, Task 2            3 29-OCT-08
         7          3 29-OCT-08 Job 3, Task 1            2
         8          3 30-OCT-08 Job 3, Task 2            1
         9          3 30-OCT-08 Job 3, Task 3            1

答案 3 :(得分:0)

我不做Oracle,而且我没有方便的Sql Server - 但这应该让你相当接近。

SELECT Tasks.*
FROM Tasks
JOIN (
   --Undone
   SELECT Job_Id
   FROM Tasks
   WHERE
     Status <> 3
   UNION
   --Done today
   SELECT Job_Id
   FROM Tasks
   WHERE
     Status = 3
     AND Completed_Date = TODAY()
) as UndoneOrDoneToday ON
   Tasks.Job_Id = UndoneOrDoneToday.Job_Id
JOIN (
   SELECT Job_Id, MIN(to_do_by_date) as NextToDoByDate
   FROM Tasks
   GROUP BY Job_id
) as NextJob ON
   Tasks.Job_Id = NextJob.Job_id
ORDER BY
   NextJob.NextToDoByDate, 
   Tasks.Job_Id, --If NextToDoByDate isn't unique, this should order jobs together
   Tasks.to_do_by_date, --This may not be needed, but would put eg., task 7 due today higher than task 6 due tomorrow
   Tasks.Task_Id --this should be last

编辑:大多数其他答案似乎按job_id,to_do_by排序。这看起来适用于示例数据,但不符合以下要求:

  

按to_be_done_by日期排序,但将所有job_id任务分组在一起   因此,首先显示具有下一个to_do_by_date任务的job_id