2017-08-23 4 views
3

Je suis en train de compter un certain nombre d'utilisateurs en fonction de leurs fichiers attribués et regroupés par les statuts de ces fichiers avec la requête suivante MySQL:Select CASE QUAND ALIAS avec COUNT ne pas retourner ZERO Valeurs

SELECT 
    (CASE WHEN F.status IS null THEN 'records' 
    WHEN F.status = 0 THEN 'prospects' 
    WHEN F.status >= 1 AND F.status < 4 THEN 'open' 
    WHEN F.status = 4 THEN 'archived' END) AS FileStatus, 
    count(DISTINCT U.id) as users 
FROM 
    users_table U 
    LEFT OUTER JOIN files_table as F on (F.user_id = U.id or F.user_id IS NULL) 
WHERE U.team = 1 
GROUP BY FileStatus DESC 

Mon problème est que si aucun utilisateur est ont un fichier avec un certain statut, la requête de retour coutume de cette ligne:

Pour l'instant, la requête renvoie des valeurs comme ceci:

+------------+-------+ 
| FileStatus | users | 
+------------+-------+ 
| prospects | 5 | 
| open  | 10 | 
| archived | 12 | 
+------------+-------+ 

Mais je li ke d'avoir zéro ou des valeurs nulles apparaissent ainsi comme ceci:

+------------+-------+ 
| FileStatus | users | 
+------------+-------+ 
| records | 0 | 
| prospects | 5 | 
| open  | 10 | 
| archived | 12 | 
+------------+-------+ 

Je suis sûr que c'est super simple mais toute aide serait très appréciée ✌️

Répondre

1

Pour obtenir tous les statuts de fichiers, vous devez avoir une table avec ces statuts. S'il n'est pas disponible, vous pouvez le produire en ligne avec une sous-requête. Deuxièmement, la condition sur l'équipe de l'utilisateur doit faire partie de la condition de jointure, sinon (lorsque vous le mettez dans la clause where), la jointure externe devient une jointure interne.

Après des commentaires sur le nombre "d'enregistrements", il n'a de toute façon plus aucun sens d'utiliser une jointure externe. Je suggère un union pour cette catégorie à la place:

SELECT  FileStatus, 
      count(DISTINCT U.id) as users 
FROM  (SELECT 0 as status, 'prospects' as FileStatus 
      UNION ALL SELECT 1, 'open' 
      UNION ALL SELECT 2, 'open' 
      UNION ALL SELECT 3, 'open' 
      UNION ALL SELECT 4, 'archived') as C 
INNER JOIN files_table as F 
     on F.status = C.status 
INNER JOIN users_table U 
     on F.user_id = U.id 
     and U.team = 1 
GROUP BY FileStatus DESC 
UNION ALL 
SELECT 'records', 
      count(*) 
FROM  users_table 
WHERE  id NOT IN (SELECT user_id FROM files_table) 
AND  team = 1 

Si vous voulez travailler avec des plages, puis revenir une extrémité basse/haute dans la sous-requête, et adapter la condition de jointure en conséquence:

SELECT  FileStatus, 
      count(DISTINCT U.id) as users 
FROM  (SELECT 0 as statusFrom, 0 statusTo, 'prospects' as FileStatus 
      UNION ALL SELECT 1, 3, 'open' 
      UNION ALL SELECT 4, 4, 'archived') as C 
INNER JOIN files_table as F 
     on F.status between C.statusFrom and C.statusTo 
INNER JOIN users_table U 
     on F.user_id = U.id 
     and U.team = 1 
GROUP BY FileStatus DESC 
UNION ALL 
SELECT 'records', 
      count(*) 
FROM  users_table 
WHERE  id NOT IN (SELECT user_id FROM files_table) 
AND  team = 1 
+0

Merci pour ça! Bien qu'il existe un moyen de grouper 'UNION ALL SELECT' dans une plage de 1 à 3 pour 'open'? Considérant que la gamme pourrait changer au fil du temps. Quelque chose comme le 'F.status> = 1 ET F.status <4' dans ma requête originale? –

+0

Voir mise à jour de ma réponse pour une gamme-alternative. – trincot

+0

Après avoir testé cela dans plusieurs scénarios, il s'avère que la valeur de 'records' est toujours 0 ... 'records' étant ceux qui n'ont aucun fichier du tout. Impossible de comprendre pourquoi ... –