2010-04-30 8 views
1

J'ai quelques tables dans une base de données d'accès:Sélectionner une requête jointe sur deux champs?

ID | LocationName 
1 | Location1 
2 | Location2 

ID | LocationID | Date | NumProductsDelivered 
1 |  1  | 12/10 |  3 
2 |  1  | 01/11 |  2 
3 |  1  | 02/11 |  2 
4 |  2  | 11/10 |  1 
5 |  2  | 12/10 |  1 

ID | LocationID | Date | NumEmployees | EmployeeType 
1 |  1  | 12/10 |  10  |  1 (=Permanent) 
2 |  1  | 12/10 |  3  |  2 (=Temporary) 
3 |  1  | 12/10 |  1  |  3 (=Support) 
4 |  2  | 10/10 |  1  |  1 
5 |  2  | 11/10 |  2  |  1 
6 |  2  | 11/10 |  1  |  2 
7 |  2  | 11/10 |  1  |  3 
8 |  2  | 12/10 |  2  |  1 
9 |  2  | 12/10 |  1  |  3 

Ce que je veux faire est de passer dans le LocationID comme paramètre et revenir quelque chose comme le tableau suivant. Donc, si je passe 2 mon LocationID, je devrais:

Date | NumProductsDelivered | NumPermanentEmployees | NumSupportEmployees 
10/10 |      |   1   |   
11/10 |   1   |   2   |   1 
12/10 |   1   |   2   |   1 

Il semble que cela devrait être une question assez simple. Je n'ai vraiment pas besoin de la première table, sauf comme un moyen de remplir la zone de liste déroulante sur le formulaire à partir duquel l'utilisateur choisit l'emplacement pour lequel il veut un rapport. Malheureusement, tout ce que j'ai fait m'a permis d'obtenir beaucoup plus de données que je n'aurais dû. Ma confusion est dans la façon de mettre en place la jointure (probablement c'est ce que je recherche ici) étant donné que je veux que les deux date et locationID soient les mêmes pour chaque ligne dans le jeu de résultats.

Toute aide serait grandement appréciée.

Merci.

EDIT: Ok - la réponse ci-après ne pas tout à fait le travail, mais il m'a fait mis sur la bonne voie et j'ai pu utiliser la requête suivante:

SELECT t1.Date, t2.NumProductsDelivered, 
    (SELECT t1a.NumEmployees 
    FROM table3 t1a 
    WHERE t1a.EmployeeType=1 AND t1a.LocationID=t1.LocationID AND t1a.Date= t1.Date) 
    AS "PermEmps", 
    (SELECT t1b.NumEmployees 
    FROM table3 t1b 
    WHERE t1b.EmployeeType=3 AND t1b.LocationID=t1.LocationID AND t1b.Date=t1.Date) 
    AS "SupportEmps" 
FROM table3 AS t1 LEFT JOIN table2 AS t2 ON (t2.Date=t1.Date) 
    AND (t2.LocationID=t1.LocationID) 
WHERE t1.LocationID=2 
GROUP BY t1.Date, t1.LocationID, t2.NumProductsDelivered; 

Cela me devient les résultats que je cherchais. Cependant, dans un cas où l'emplacement a une pause entre les produits livrés, je ne vois pas les bons résultats. Il semble que le jeu d'enregistrements s'arrête dès qu'il y a une ligne vide et qu'il ne se relève plus jamais. Alors, où je pourrais attendre à voir ceci:

Date | NumProductsDelivered | NumPermanentEmployees | NumSupportEmployees 
10/10 |      |   1   |   
11/10 |   1   |   2   |   1 
12/10 |   1   |   2   |   1 
01/10 |   2   |      |   1 
06/10 |   1   |      | 

Je vois seulement ceci:

Date | NumProductsDelivered | NumPermanentEmployees | NumSupportEmployees 
10/10 |      |   1   |   
11/10 |   1   |   2   |   1 
12/10 |   1   |   2   |   1 
01/10 |   2   |      |   1 
+0

Vous ne devriez pas avoir à GROUP BY t1.LocationID puisque vous ne le sélectionnant et il est toujours 2. Je voudrais aussi recommande d'utiliser de meilleurs noms que "t1" pour la lisibilité.L'autre problème est un mystère ... Avez-vous une relation 1-à-1 entre t1 et t2? Aussi, essayez de sortir la jointure et sous-sélectionne pour voir si vous obtenez tous les dates dont vous avez besoin (je vais ajouter à ma réponse ci-dessous) –

Répondre

0

Quelque chose comme cela devrait fonctionner:

[original supprimé]

Essayez ceci à la place (non testé):

select t3.date, t2.numproductsdelivered, 
    (select sum(t3.numemployees) 
    from table3 t3a 
    where t3a.locationid = t3.locationid and t3a.date = t3.date and t3a.employeetype = 1 
) as numpermanentemployees, 
    (select sum(t3.numemployees) 
    from table3 t3b 
    where t3b.locationid = t3.locationid and t3b.date = t3.date and t3b.employeetype = 3 
) as numsupportemployees 
from table3 as t3 
left join table2 as t2 on t2.locationid = t3.locationid and t2.date = t3.date 
where t3.locationid = 2 
group by t3.date, t2.numproductsdelivered 

Si vous ne me dérangeait pas d'avoir des lignes distinctes pour chaque type d'employé, il pourrait être simplifié:

select t3.date, t2.numproductsdelivered, t3.employeetype, sum(t3.numemployees) as numemployees 
from table3 as t3 
left join table2 as t2 on t2.locationid = t3.locationid and t2.date = t3.date 
where t3.locationid = 2 and t3.employeetype in (1, 3) 
group by t3.date, t2.numproductsdelivered, t3.employeetype 

Edit: Essayez cette requête:

SELECT t1.Date 
FROM table3 AS t1 
WHERE t1.LocationID=2 
GROUP BY t1.Date 

... et voir si vous obtenir toutes les dates.

Ensuite, ajoutez la gauche rejoindre:

SELECT t1.Date, t2.NumProductsDelivered 
FROM table3 AS t1 LEFT JOIN table2 AS t2 ON (t2.Date=t1.Date) 
    AND (t2.LocationID=t1.LocationID) 
WHERE t1.LocationID=2 
GROUP BY t1.Date, t1.LocationID, t2.NumProductsDelivered; 

Si cela fait une jointure gauche, il supprimera les lignes de t1 qui ne sont pas une ligne dans t2. Essayez explicitement de définir une jointure OUTER gauche et voyez si cela fonctionne. Le SGBDR J'ai utilisé le plus par défaut pour l'extérieur, mais peut-être que le vôtre (Access) est par défaut à l'intérieur. Donc, je pense que ce qui suit va fonctionner (ajouter "OUTER" et supprimer "t1").LocationID "):

SELECT t1.Date, t2.NumProductsDelivered, 
    (SELECT t1a.NumEmployees 
    FROM table3 t1a 
    WHERE t1a.EmployeeType=1 AND t1a.LocationID=t1.LocationID AND t1a.Date= t1.Date) 
    AS "PermEmps", 
    (SELECT t1b.NumEmployees 
    FROM table3 t1b 
    WHERE t1b.EmployeeType=3 AND t1b.LocationID=t1.LocationID AND t1b.Date=t1.Date) 
    AS "SupportEmps" 
FROM table3 AS t1 LEFT OUTER JOIN table2 AS t2 ON (t2.Date=t1.Date) 
    AND (t2.LocationID=t1.LocationID) 
WHERE t1.LocationID=2 
GROUP BY t1.Date, t2.NumProductsDelivered; 
+0

Quelques notes: 1. J'ai dû changer les parties 'grouper par' et 'où' de la requête ou Acccess ne me laisserait même pas le sauver. 2. En essayant de l'exécuter, j'obtiens une erreur: Vous avez essayé d'exécuter une requête qui n'inclut pas l'expression spécifiée 'numproductsdelivered' dans le cadre d'une fonction d'agrégation. – wtollett

+0

Oui, vous ne pouvez pas sélectionner tout ce que vous n'avez pas groupé (sauf pour les valeurs agrégées) ... Dans ce cas, je pense que vous pouvez simplement changer de groupe par t3.date, t2.numproductsdelivered, puisque ce groupement supplémentaire a gagné ' t changer les résultats (vous avez seulement un numproductsdelivered à chaque date). J'ai corrigé ma réponse (peut-être pas complètement) –

+0

Cela ne fonctionnait toujours pas, mais cela m'a aidé à trouver une réponse qui semble fonctionner sauf dans un cas (voir ci-dessus). – wtollett

0

Je pense que cela fonctionnerait:

DECLARE @LocationId int 

SET @LocationId=2 

SELECT L2.LocationId, L2.Date, COUNT(DISTINCT NumProductsDelivered) as NumProductsDelivered, 
SUM(case when L2.EmployeeType =1 then NumEmployees else 0 end) as NumPermanentEmployees, 
SUM(case when L2.EmployeeType =3 then NumEmployees else 0 end) as NumSupportEmployees 
FROM L1 
    RIGHT JOIN L2 
     ON L1.LocationID=L2.LocationID 
     AND L1.Date=L2.Date 
WHERE L2.Locatio[email protected] 
GROUP BY L2.LocationId, L2.Date 
+0

Ce qui ressort est "cas" ... Pourquoi n'ai-je pas pensé à ça? :) Je ne sais pas si le reste fonctionne ... –

+0

Ceci est une réponse T-SQL pour une question sur une base de données Access/Jet/ACE (je ne vois aucune mention de SQL Server dans la question elle-même ou dans les balises). -1 pour ne pas avoir fait attention et fournir une réponse non-fonctionnelle. –

+0

Oui, vous avez raison. Je n'ai pas vu que c'était à propos d'Access, mon erreur. Avec Access au lieu de CAS, vous devez utiliser IIF pour obtenir le même résultat. – Claudia

Questions connexes