2010-09-30 6 views
2

j'ai le schéma de base de données ci-dessous (les noms changés pour protéger les innocents)question SQL UNION lors du comptage des enregistrements

Code Table 

| code_id | code_desc | 
|---------|-----------| 
| 1  | good  | 
|---------|-----------| 
| 2  | bad  | 
|---------|-----------| 
| 3  | ugly  | 
|---------|-----------| 

Foo Table        AssignedFoo Table 

| foo_id | foo_desc | foo_dt |  | assn_id | foo_id | code_id | 
|--------|----------|-----------|  |---------|--------|---------| 
| 101 | red  | 1/1/2000 |  | 301  | 101 | 1  | 
|--------|----------|-----------|  |---------|--------|---------| 
| 102 | green | 6/1/2000 |  | 302  | 102 | 2  | 
|--------|----------|-----------|  |---------|--------|---------| 
| 102 | blue  | 12/1/2000 | 
|--------|----------|-----------| 

Bar Table        AssignedBar Table 

| bar_id | bar_desc | bar_dt |  | assn_id | foo_id | code_id | 
|--------|----------|-----------|  |---------|--------|---------| 
| 201 | gold  | 12/1/2000 |  | 401  | 201 | 1  | 
|--------|----------|-----------|  |---------|--------|---------| 
| 202 | silver | 1/1/2001 |  | 402  | 202 | 3  | 
|--------|----------|-----------|  |---------|--------|---------| 
| 202 | bronze | 6/1/2001 | 
|--------|----------|-----------| 

Je veux compter le nombre d'enregistrements qui sont mis en correspondance à la table de code, peu importe si elles sont foos ou barres. J'avais cependant que la requête suivante fonctionnerait.

SELECT 
    COUNT(c.code_id) AS coded, 
    c.code_desc 
FROM 
    code c 
    INNER JOIN assignedfoo af ON af.code_id = c.code_id 
    INNER JOIN foo f ON f.foo_id = af.foo_id 
WHERE 
    f.foo_dt >= [start date] AND 
    f.foo_dt <= [end date] 
GROUP BY 
    c.code_desc 

UNION ALL 

SELECT 
    COUNT(c.code_id) AS coded, 
    c.code_desc 
FROM 
    code c 
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id 
    INNER JOIN bar b ON b.bar_id = ab.bar_id 
WHERE 
    b.bar_dt >= [start date] AND 
    b.bar_dt <= [end date] 
GROUP BY 
    c.code_desc 

Malheureusement, je reçois le jeu de résultats suivant

| coded | code_desc | 
|-------|-----------| 
| 1  | good  | 
|-------|-----------| 
| 1  | good  | 
|-------|-----------| 
| 1  | bad  | 
|-------|-----------| 
| 1  | ugly  | 
|-------|-----------| 

Ce que je veux est ce

| coded | code_desc | 
|-------|-----------| 
| 2  | good  | 
|-------|-----------| 
| 1  | bad  | 
|-------|-----------| 
| 1  | ugly  | 
|-------|-----------| 

Toutes les suggestions sur la façon de résoudre ce problème?

Toute aide serait grandement appréciée.

Merci!

Répondre

1

Je pense que vous avez simplement besoin de déplacer le groupe par/compte en dehors de votre syndicat comme ceci:

select count(a.code_id) as Coded, a.code_desc 
from (
SELECT 
    c.code_id, 
    c.code_desc 
FROM 
    code c 
    INNER JOIN assignedfoo af ON af.code_id = c.code_id 
    INNER JOIN foo f ON f.foo_id = af.foo_id 
WHERE 
    f.foo_dt >= [start date] AND 
    f.foo_dt <= [end date] 

UNION ALL 

SELECT 
    c.code_id, 
    c.code_desc 
FROM 
    code c 
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id 
    INNER JOIN bar b ON b.bar_id = ab.bar_id 
WHERE 
    b.bar_dt >= [start date] AND 
    b.bar_dt <= [end date] 
) a 
group by a.code_desc 
0

utilisent ce

Select COUNT(UnionTable.coded),UnionTable,code_description from 

(SELECT 
    COUNT(c.code_id) AS coded, 
    c.code_desc code_description 
FROM 
    code c 
    INNER JOIN assignedfoo af ON af.code_id = c.code_id 
    INNER JOIN foo f ON f.foo_id = af.foo_id 
WHERE 
    f.foo_dt >= [start date] AND 
    f.foo_dt <= [end date] 
GROUP BY 
    c.code_desc 

UNION ALL 

SELECT 
    COUNT(c.code_id) AS coded, 
    c.code_desc code_description 
FROM 
    code c 
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id 
    INNER JOIN bar b ON b.bar_id = ab.bar_id 
WHERE 
    b.bar_dt >= [start date] AND 
    b.bar_dt <= [end date] 
GROUP BY 
    c.code_desc) UnionTable 

    group by UnionTable.code_description 
+0

ou le faire le chemin a fait @ Joe 6 secondes il y a – Thakur

+0

Je suis content de ne pas arrêter de se gratter le nez ou vous auriez m'a battu! :-) –

0

Faire le syndicat avant de compter:

SELECT 
    COUNT(*) AS coded, 
    x.code_desc 
FROM (

    SELECT 
    c.code_desc, f.foo_dt 
    FROM 
    code c 
    INNER JOIN assignedfoo af ON af.code_id = c.code_id 
    INNER JOIN foo f ON f.foo_id = af.foo_id 

    UNION ALL 

    SELECT 
    c.code_desc, f.foo_dt 
    FROM 
    code c 
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id 
    INNER JOIN bar b ON b.bar_id = ab.bar_id 

) x 
WHERE 
    x.foo_dt >= [start date] AND 
    x.foo_dt <= [end date] 
GROUP BY 
    x.code_desc 
0

Lorsque vous effectuez une union en dehors de votre compte, vous "ajoutez" des lignes au premier ensemble. Si vous ne spécifiez pas "all", il tentera de renvoyer un ensemble DISTINCT, ainsi deux lignes contenant "GOOD 1" donneront une seule ligne "GOOD 1". Si vous faites UNION ALL, il ajoute simplement mais n'ajoute pas.

Ce que vous devez faire est de somme au-dessus de l'union:

SELECT c.code_desc, s.COUNT(NUM) 
FROM 
Code c JOIN 
(
    SELECT code_id, COUNT(*) AS NUM 
     FROM AssignedFoo af 
     JOIN Foo f on af.foo_id = f.foo_id 
     WHERE f.foo_dt >= [start date] 
     AND f.foo_dt <= [end date] 
    GROUP BY CODE_ID 
    UNION ALL 
    SELECT CODE_ID, COUNT(*) AS NUM 
     FROM AssignedBar ab 
     JOIN Bar b on ab.bar_id = b.bar_id 
     WHERE b.bar_dt >= [start date] 
     AND b.bar_dt <= [end date] 
    GROUP BY code_id 
) s ON c.code_id = s.code_id 
GROUP BY c.code_id 
Questions connexes