存在两个表,任务表worktodo和完成任务表workdone,worktodo记录所有工作人员worker的任务,而workdone记录完成的部分,一条workorder可能分多次记录到workdone中。结构如下:
CREATE TABLE worktodo ( workorder VARCHAR(32), worker VARCHAR(64), duedate DATETIME, PRIMARY KEY workorder ); CREATE TABLE workdone ( workorder VARCHAR(32), donedate DATETIME );
示例数据:
worktodo: workorder worker duedate 10001 JOE 2012-01-01 10002 JOE 2012-01-02 10003 FRED 2012-01-03 10004 BILL 2013-12-31 workdone: workerorder donedate 10001 2012-01-31 10002 2011-12-30 10002 2012-01-04
期望统计每个worker的任务总数以及超期的任务,超期任务指的是donedate > duedate或者没有workdone记录且duedate < 当前时间NOW。
就以上数据而言,JOE的总数为2,10001超期,10002由于在workdone中有在duedate之前的记录,不算超期;FRED总数为1,10003由于无workdone记录且duedate小于NOW,超期;BILL总数为1,10004的duedate未到,则不算超期。综上,预期结果如下:
Desired: worker num_total_workorders num_late_workorders BILL 1 0 FRED 1 1 JOE 2 1
如何编写单条SQL实现该功能?
本题来源stackflow
本题是个典型的行转列技巧的应用,这里复杂的一点是:workdone表中同一workorder会有多条记录。我们可以取其最早的一条作为判断依据。具体SQL如下,这里的getdate()属于SQLServer的函数,其余各RDBMS一致。
select t1.worker, sum(1) as num_total_workorders, sum ( case when t2.donedate is null and t1.duedate < getdate() then 1 when t2.donedate > t1.duedate then 1 else 0 end ) as num_late_workorders from worktodo t1 left outer join ( select workorder,min(donedate) as donedate from workdone group by workorder ) t2 on t1.workorder = t2.workorder group by t1.worker
The post 根据两表统计任务完成情况 appeared first on SQLParty.