2013-05-21 3 views
2

У меня есть база данных MS SQLServer 2008 с двумя таблицами, worktodo и workdone:присоединиться к ранним ребенком записи

CREATE TABLE worktodo 
(
    workorder VARCHAR(32), 
    worker VARCHAR(64), 
    duedate DATETIME, 
    PRIMARY KEY workorder 
); 
CREATE TABLE workdone 
(
    workorder VARCHAR(32), 
    donedate DATETIME 
); 

И я ищу запрос, возвращающий для каждого работника, общее количество worktodos и общее количество поздних worktodos, где опоздание определяется как donedate> duedate, или duedate> NOW, и нет записи workdone.

Простой код, но мне нужен запрос, которым может управлять довольно простой инструмент отчетности.

Любые идеи?

Редакция: Добавлена ​​выборка данные:

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: 
worker  donedate 
10001  2011-01-01 
10002  2011-12-30 
10002  2012-01-04 

Desired: 
worker num_total_workorders num_late_workorders 
BILL  1      0 
FRED  1      1 
JOE  2      1 

Билл имеет один worktodo, который не имеет детей workdones. Но потому, что duedate в будущем, поэтому у него есть один рабочий заказ и никаких поздних рабочих заказов.

У Fred есть один worktodo, у которого нет детей. Но поскольку duedate в прошлом, поэтому у него есть один рабочий заказ и один поздний рабочий заказ.

У Джо есть два рабочих стола. Workorder 10001 имел duedate от 2012-01-01, но это не было сделано до 2012-01-31, так что поздно. Workorder 10002 имеет duedate от 2012-01-02, но это самый ранний workdone был сделан до этого, в 2011-12-30, так что не поздно. То, что есть еще один workdone для 10002 с donedate, который позже, чем duedate, не имеет никакого отношения. Это приводит к тому, что Джо имеет два рабочих места и один поздний рабочий заказ.

(Кроме того, предположим, что порядок работы является первичным ключом, на worktodo).

+2

Имеются примеры данных и желаемого результата? –

+0

Является ли 'donedate' нулевым столбцом в workdone? – Tim

ответ

1

Вы можете использовать SUM (сравнение CASE 1 ELSE 0 END), чтобы суммировать все случаи, когда сравнение истинно. Как это. Я исхожу из предположения, что для данного рабочего порядка будет только один отчет о работе.

SELECT worktodo.worker, COUNT(worktodo.workorder) AS TotalWorkToDo, 
    SUM(CASE WHEN (workdone.workorder IS NULL AND duedate < getdate()) 
     OR donedate > duedate 
    THEN 1 ELSE 0 END) AS TotalLateWorkToDo 
FROM worktodo 
LEFT OUTER JOIN workdone 
    ON worktodo.workorder = workdone.workorder 
GROUP BY worktodo.worker 

Если несколько рабочих записей для данного рабочего порядка.

SELECT worktodo.worker, COUNT(worktodo.workorder) AS TotalWorkToDo, 
    SUM(CASE WHEN (workdone.workorder IS NULL AND duedate < getdate()) 
     OR donedate > duedate 
    THEN 1 ELSE 0 END) AS TotalLateWorkToDo 
FROM worktodo 
LEFT OUTER JOIN 
    (SELECT workorder, min(donedate) AS donedate FROM workdone 
     GROUP BY workorder) as workdone 
    ON worktodo.workorder = workdone.workorder 
GROUP BY worktodo.worker 
+0

Для любого заданного рабочего порядка будет создано несколько записей о работе, поэтому ваш первый пример не относится к делу. Что касается вашего второго, у него отсутствуют команды GROUP BY. –

+0

Добавил группу (мальчик, который неловко). Я включил обе версии, так как не был уверен, что это отношения 1: 1 или 1: многие. –

+0

Столбец «worktodo.worker» недействителен в списке выбора, потому что он не содержится ни в агрегатной функции, ни в предложении GROUP BY. –

Смежные вопросы