2017-10-17 2 views
0

J'ai les tableaux suivants produits et tests.Joindre deux tables et compter, éviter zéro si l'enregistrement n'est pas disponible dans la deuxième table

select id,pname from products;              
+----+---------+                 
| id | pname |                 
+----+---------+                 
| 1 | prd1 |                 
| 2 | prd2 |                 
| 3 | prd3 |                 
| 4 | prd4 |                 
+----+---------+              

select pname,testrunid,testresult,time from tests;      
+--------+-----------+------------+-------------+         
| pname | testrunid | testresult | time  |         
+--------+-----------+------------+-------------+         
| prd1 |  800 | PASS  | 2017-10-02 |         
| prd1 |  801 | FAIL  | 2017-10-16 |         
| prd1 |  802 | PASS  | 2017-10-02 |         
| prd1 |  803 | NULL  | 2017-10-16 |         
| prd1 |  804 | PASS  | 2017-10-16 |         
| prd1 |  805 | PASS  | 2017-10-16 |         
| prd1 |  806 | PASS  | 2017-10-16 |         
+--------+-----------+------------+-------------+  

J'aime compter les résultats des tests pour les produits et s'il n'y a pas de résultat disponible, pour un produit juste montrer un zéro pour elle. quelque chose comme tableau suivant:

+--------+------------+-----------+----------------+---------------+    
| pname | total_pass | total_fail| pass_lastweek | fail_lastweek |    
+--------+------------+-----------+----------------+---------------+    
| prd1 |  5  |  1  |  3   |  1  |    
| prd2 |  0  |  0  |  0   |  0  |    
| prd3 |  0  |  0  |  0   |  0  |    
| prd4 |  0  |  0  |  0   |  0  |    
+--------+------------+-----------+----------------++--------------+ 

J'ai essayé différentes questions comme suit, qui travaille pour un seul produit et est incomplet:

SELECT pname, count(*) as pass_lastweek FROM tests where testresult = 'PASS' AND time 
>= '2017-10-11' and pname in (select pname from products) group by pname;  
+-------------+---------------+             
| pname  | pass_lastweek |             
+-------------+---------------+             
| prd1  |   3 |             
+-------------+---------------+ 

il semble si fondamental mais je ne suis pas capable de l'écrire , une idée?

+0

PName ne serait pas une colonne dans une table de test conçue de manière sensée. Au-delà de cela, c'est incroyablement basique et serait entièrement abordé dans n'importe quel livre d'introduction ou tutoriel de base. – Strawberry

+0

'SELECT a.pname, b.testrunid FROM produits comme A LEFT JOIN tests comme B sur a.pname = b.pname où b.testresulty = 'PASS' et b.time> = '2017-10-11' et le groupe par a.pname' – parkway

Répondre

3

Utiliser l'agrégation conditionnelle. La fonction COUNT compte automatiquement les valeurs NULL, donc il n'y a pas besoin de s'en occuper.

select p.pname, 
     count(case when testresult = 'PASS' then 1 end) as total_pass, 
     count(case when testresult = 'FAIL' then 1 end) as total_fail, 
     count(case when testresult = 'PASS' and time >= curdate() - INTERVAL 6 DAY then 1 end) as pass_lastweek , 
     count(case when testresult = 'FAIL' and time >= curdate() - INTERVAL 6 DAY then 1 end) as fail_lastweek , 
from products p 
left join tests t on t.pname = p.pname 
group p.id, p.pname 
0

Généralement, vous devez LEFT JOIN la première table avec le second avant le regroupement. La jointure vous donnera une ligne pour chaque produit (même s'il n'y a pas de résultats de test pour la joindre; INNER JOIN exclurait les produits sans tests associés) + une ligne supplémentaire pour chaque résultat de test (au-delà de la première). Ensuite, vous pouvez les grouper.

SELECT products.*, tests.* FROM products 
LEFT JOIN tests ON products.pname = tests.pname 
GROUP BY products.id 

Aussi, je fortement vous recommandons d'utiliser une colonne product_id dans le tableau des tests, plutôt que d'utiliser pname (en cas de changement de products.pname, l'ensemble de votre pauses DB, sauf si vous mettez à jour également le champ pname en nature chaque résultat de test). La requête générale serait alors ressembler à ceci:

SELECT products.*, tests.* FROM products 
LEFT JOIN tests ON products.id = tests.product_id 
GROUP BY products.id 
0

J'ai utilisé 2 requêtes, le premier avec nombre conditionnel et le second est de changer tous les valeurs nulles en 0:

select pname, 
    case when total_pass is null then 0 else total_pass end as total_pass, 
    case when total_fail is null then 0 else total_fail end as total_fail, 
     case when pass_lastweek is null then 0 else pass_lastweek end as pass_lastweek, 
     case when fail_lastweek is null then 0 else fail_lastweek end asfail_lastweek from (
    select products.pname, 
      count(case when testresult = 'PASS' then 1 end) as total_pass, 
      count(case when testresult = 'FAIL' then 1 end) as total_fail, 
      count(case when testresult = 'PASS' and time >= current_date -7 DAY then 1 end) as pass_lastweek , 
      count(case when testresult = 'FAIL' and time >= current_date -7 DAY then 1 end) as fail_lastweek , 
    from products 
    left join tests on tests.pname = products.pname 
    group 1) t1