2017-10-19 2 views
1

J'ai un tableau moves.PostgreSQL Groupez les valeurs par catégorie, comptez et calculez le pourcentage

uuid | tag | ... 
-----| ----|---- 
abc | 520 | ... 
def | 510 | ... 
ghi | 500 | ... 
jkl | 310 | ... 
mno | 200 | ... 

Le tag correspond au type de déménagement. Nous parlons de mouvements au beach-volley. Le premier numéro, par ex. le 5 de 520, est la catégorie. "Service" dans ce cas. Au total, j'ai six catégories:

  1. attaque (catégorie 1, par exemple 100, 110 et 120)
  2. Block (catégorie 2)
  3. Dig (catégorie 3)
  4. Réception (catégorie 4)
  5. service (catégorie 5)
  6. réglage (catégorie 6)

Le dernier numéro, c'est-à-dire le 20 de 520, est le résultat. "Win" dans ce cas. Chaque catégorie a 3 résultats possibles:

  1. Erreur (00)
  2. zéro (10)
  3. Win (20)

Voici les balises de la table ci-dessus

  1. 520 - Service Win (qui est un As)
  2. 510 - service zéro
  3. 500 - Erreur de service
  4. 310 - Dig zéro
  5. 200 - Erreur bloc

Voici ce que je voudrais obtenir: Donne-moi le nombre d'erreurs, des zéros , gagne pour chaque catégorie en valeurs absolues et relatives.

J'ai essayé le suivant

select *, 
    (attack_error::float/attacks::float * 100) as attack_error_percentage, 
    (attack_zero::float/attacks::float * 100) as attack_zero_percentage, 
    (attack_win::float/attacks::float * 100) as attack_win_percentage 
    from (
     select 
      count(*) filter (where tag = 100) as attack_error, 
      count(*) filter (where tag = 110) as attack_zero, 
      count(*) filter (where tag = 120) as attack_win, 
      count(*) filter (where tag = 100 or tag = 110 or tag = 120) as attacks 
     from moves 
     where match_uuid = 'd7eea231-a63d-4d73-b48f-5ca8541ec9cf' and set = 1 
    ) 
as attack_stats 

et a obtenu quelque chose comme ça

att_error | att_zero | att_win | total | att_error_% | att_zero_% | att_win_% 
----------|----------|---------|-------|-------------|------------|---------- 
1   | 3  | 13  | 17 | 5.88  | 17.65  | 76.47 

Cependant, il ne se sent pas bien que je dois répéter les questions encore et encore pour toutes les différentes catégories avec tous leurs résultats.

Ce que j'aimerais vraiment obtenir, c'est quelque chose comme ça.

category | error | zero | win | total | error_% | zero_% | win_% 
---------|-------|------|-----|-------|---------|--------|------ 
1  | 2  | 4 | 6 | 12 | 0.16 | 0.33 | 0.5 
2  | 3  | 8 | 13 | 24 | 0.125 | 0.33 | 0.54 
3  | ... | ... | ... | ... | ...  | ... | ... 
4  | ... | ... | ... | ... | ...  | ... | ... 
5  | ... | ... | ... | ... | ...  | ... | ... 
6  | ... | ... | ... | ... | ...  | ... | ... 

Des idées?

Répondre

1

Tenir compte la création de votre catégorie colonne conditionnelle avec CASE déclaration et l'inclure comme GROUP BY dans l'ensemble table dérivée requête

select *, 
    (error::float/total::float * 100) as error_percentage, 
    (zero::float/total::float * 100) as zero_percentage, 
    (win::float/total::float * 100) as win_percentage 
    from (
     select 
      case substring(tag::text, 1, 1) 
       when '1' then 'Attack' 
       when '2' then 'Block' 
       when '3' then 'Dig' 
       when '4' then 'Reception' 
       when '5' then 'Service' 
       when '6' then 'Setting' 
      end as category, 
      count(*) filter (where tag - round(tag/100, 0)*100 = 0) as error, 
      count(*) filter (where tag - round(tag/100, 0)*100 = 10) as zero, 
      count(*) filter (where tag - round(tag/100, 0)*100 = 20) as win, 
      count(*) filter (where tag - round(tag/100, 0)*100 <= 20) as total 
     from moves 
     where match_uuid = 'd7eea231-a63d-4d73-b48f-5ca8541ec9cf' and set = 1 
     group by 
      case substring(tag::text, 1, 1) 
       when '1' then 'Attack' 
       when '2' then 'Block' 
       when '3' then 'Dig' 
       when '4' then 'Reception' 
       when '5' then 'Service' 
       when '6' then 'Setting' 
      end 
    ) 
as attack_stats 
+0

Il fonctionne en quelque sorte. Je reçois la disposition de table attendue mais seule la ligne Attack a des résultats. Toutes les autres lignes sont vides. Je suppose que c'est parce que nous utilisons les valeurs d'attaque codées en dur ('100',' 110', '120'). Une idée de comment peupler les autres rangées? – zemirco

+0

Je n'ai pas remarqué mais vos agrégats conditionnels filtrent uniquement les valeurs * attack *: 'count (*) filter (où tag = 100)'. Je me suis ajusté pour accommoder les autres niveaux. Je suppose que les valeurs sont en incrément de 10, 0/10/20. – Parfait

+0

Merci! Fonctionne comme prévu Une dernière question. Est-il possible de toujours obtenir 6 lignes même s'il manque une catégorie? Par exemple, le match vient de commencer et il n'y a pas encore de blocs (catégorie 2). En ce moment, j'ai simplement 5 lignes. Pourrais-je toujours obtenir toutes les lignes avec 0 valeurs pour les catégories manquantes? – zemirco