2013-05-21 7 views
2

J'ai une base de données MS SqlServer 2008 avec deux tables, worktodo et workdone:se joindre à l'enfant plus tôt dossier

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

Je suis à la recherche d'une requête qui renverra, pour chaque travailleur, le nombre total de worktodos, et le nombre total de worktodos en retard, où late est défini comme donedate> duedate, ou duedate> NOW et il n'y a pas d'enregistrement workdone.

Très facile à faire dans le code, mais j'ai besoin d'une requête qui peut être exécutée par un outil de reporting plutôt simple.

Des idées?

ÉDITÉ: données exemple Ajouté:

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 

Bill a un worktodo, qui n'a pas workdones enfant. Mais parce que le futur est dans le futur, il a donc un ordre de travail et aucun travail en retard.

Fred a un worktodo, qui n'a pas de workdones enfant. Mais parce que le duedat est dans le passé, il a donc un travail et un travail en retard.

Joe a deux worktodos. L'ordre de travail 10001 a été daté du 01-01-2012, mais il n'a pas été fait avant le 2012-01-31, alors il est tard. L'ordre de travail 10002 a été daté du 2012-01-02, mais le plus tôt le workdone a été fait avant, le 2011-12-30, il n'est donc pas trop tard. Qu'il y ait un autre workdone pour 10002 avec un donatate qui est postérieur au duedate n'a aucune pertinence. Ce qui résulte en Joe ayant deux ordres de travail, et un travail en retard.

(Supposons également que workorder est la clé primaire, sur worktodo).

+2

Données d'échantillon disponibles et résultat souhaité? –

+0

Est-ce que donedate est une colonne nullable dans workdone? – Tim

Répondre

1

Vous pouvez utiliser SUM (comparaison CASE THEN 1 ELSE 0 END) pour totaliser tous les cas où la comparaison est vraie. Comme ça. Je fais l'hypothèse qu'il n'y aura qu'un seul enregistrement workdone pour un travail donné.

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 

Si plusieurs enregistrements Workdone pour un travail donné.

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

Il y aura plusieurs enregistrements de workdone pour un workorder donné, donc votre premier exemple n'est pas à propos. Quant à votre deuxième, il manque des GROUP BY. –

+0

Ajout du groupe par (garçon qui est embarrassant). J'ai inclus les deux versions puisque je n'étais pas sûr si c'était une relation 1: 1 ou 1: plusieurs. –

+0

La colonne 'worktodo.worker' n'est pas valide dans la liste de sélection car elle n'est contenue ni dans une fonction d'agrégat ni dans la clause GROUP BY. –