Mysql
 sql >> Base de données >  >> RDS >> Mysql

Filtrage et regroupement des données d'une table avec des paires clé/valeur

Une partie de votre problème est que vous utilisez une fonction d'agrégation dans la liste SELECT mais que vous n'utilisez pas de GROUP BY . Vous devriez utiliser un GROUP BY semblable à ceci :

GROUP BY d.testId, d.rowId

Chaque fois que vous utilisez une fonction d'agrégation et que vous avez d'autres colonnes dans votre sélection, elles doivent être regroupées par. Votre requête complète devrait donc être :

select d.testId,
  d.rowId,
  max(if(f.keyName='voltage',f.keyValue,NULL)) as 'voltage',
  max(if(f.keyName='temperature',f.keyValue,NULL)) as 'temperature',
  max(if(f.keyName='velocity',f.keyValue,NULL)) as 'velocity' 
from tests t  
inner join data d 
  on t.testId = d.testId  
inner join data c 
  on t.testId = c.testId 
  and c.rowId = d.rowId  
join data f 
  on f.testId = t.testId 
  and f.rowId = d.rowId  
where (d.keyName = 'voltage' and d.keyValue < 5) 
  and (c.keyName = 'temperature' and c.keyValue = 30) 
  and (t.testType = 'testType1')
GROUP BY d.testId, d.rowId

Notez que votre structure de données réelle n'est pas présentée dans votre question d'origine. Il semble que cela puisse être consolidé comme suit :

select d.testid,
  d.rowid,
  max(case when d.keyName = 'voltage' and d.keyValue < 5 then d.keyValue end) voltage,
  max(case when d.keyName = 'temperature' and d.keyValue =30 then d.keyValue end) temperature,
  max(case when d.keyName = 'velocity' then d.keyValue end) velocity
from tests t
left join data d
  on t.testid = d.testid
group by d.testid, d.rowid

Voir SQL Fiddle avec démo . Cela donne le résultat avec une seule jointure aux data tableau :

| TESTID | ROWID | VOLTAGE | TEMPERATURE | VELOCITY |
-----------------------------------------------------
|      1 |     1 |       4 |          30 |       20 |
|      1 |     2 |       4 |          30 |       21 |
|      2 |     1 |       4 |          30 |       30 |
|      2 |     2 |       4 |          30 |       31 |