2017-09-05 1 views
0

J'ai cette requête et le résultat est dans plusieurs lignes, chacun est un événement et son numéro de compte respectif.Comment joindre tous les COUNT retournés dans plusieurs lignes à une seule ligne (POSTGRESQL)

SELECT u.name, l.event, COUNT (l.event) 
FROM log AS l LEFT JOIN user AS u ON u.id = l.userid 
GROUP BY u.name, l.event 

Le résultat est comme ceci:

------------------------------------------ 
| user | event | count | 
------------------------------------------ 
| user_1  | event_1  | 12   | 
| user_1  | event_2  | 6   | 
| user_1  | event_3  | 9   | 
| user_2  | event_1  | 16   | 
| ...  | ...   | ...   | 

Le problème est que j'ai besoin ce compte comme paramètres (colonnes) dans une seule ligne de résultat, où chaque ligne représente un seul utilisateur, quelque chose comme ça :

-------------------------------------------------------------- 
| user | event_1 | event_2 | event_3 | 
-------------------------------------------------------------- 
| user_1  | 12   | 6    | 9    | 
| user_2  | 16   | 0    | 13   | 
| ...  | ...   | ...   | ...   | 

Peut-être que je peux le faire avec une requête de sélection? Avec une sorte de fonction qui fait une boucle ou quelque chose de similaire?

Merci!

EDIT 1: Je ne sais pas les événements pour les écrire dans le code

EDIT 2: Je vois qu'il n'y a pas moyen trivial de le faire avec une simple requête SQL, donc j'utilise python avec pandas géants à fais ceci. Jetez un oeil à How to convert a column of string to numerical?

+0

Vous pouvez utiliser PIVOT. J'ai eu un type de question similaire. PIVOT sur le champ l.event. Besoin de rafraîchir ma syntaxe avant de corriger le code pour vous. –

+0

Rechercher un tableau croisé. Qui est le consommateur de cette requête? Sortie json est le moyen facile de l'avoir complètement dynamique. Est-ce que ça va sortir json? –

Répondre

0

Si vous connaissez les événements, vous pouvez utiliser l'agrégation conditionnelle:

SELECT name, 
     MAX(CASE WHEN event = 'event_1' THEN cnt ELSE 0 END) as event_1, 
     MAX(CASE WHEN event = 'event_2' THEN cnt ELSE 0 END) as event_2, 
     MAX(CASE WHEN event = 'event_3' THEN cnt ELSE 0 END) as event_3 
FROM (SELECT u.name, l.event, COUNT(l.event) as cnt 
     FROM user u LEFT JOIN 
      log l 
      ON u.id = l.userid 
     GROUP BY u.name, l.event 
    ) ul 
GROUP BY name; 

je suis passé le LEFT JOIN. Il semble plus probable que vous souhaitiez conserver tous les utilisateurs, même s'il n'y a aucun message de journal correspondant.

+0

Malheureusement, je ne connais pas les événements, en fait, il y a environ 80 événements dans la base de données. de toute façon, l'astuce pour la jointure gauche est très utile, merci. –

0

Essayez et voir si cela fonctionne ..

Select [event_1],[event_2],[event_3] from 

(SELECT u.name, l.event FROM log AS l LEFT JOIN user AS u ON u.id = l.userid) s1 

PIVOT (COUNT(l.event) FOR u.name in ([event_1],[event_2],[event_3])) as p1 
+0

effectivement et malheureusement, c'est environ 80 événements et je ne les connais pas pour écrire dans le code. Mais je n'ai jamais utilisé la fonction PIVOT avant, je vais jeter un oeil à cela, merci –

+0

Cette question est marquée Postgresql pas SQL Server. –

+0

Cool homme @ClodoaldoNeto –