Plusieurs COUNT(*) avec UNION ?

Eléphanteau du PHP | 19 Messages

28 juin 2006, 20:26

Salut à tous,

Je me trouve confronté à un petit problème.
Il me faudrait faire plusieurs COUNT(*) sur une même table mais avec des conditions différentes (WHERE).

En fait, il me faut faire cette requete, mais pour toutes les lettres:
SELECT COUNT(*) AS lettre_a FROM users WHERE nom LIKE 'a%'

Donc en fait:

SELECT COUNT(*) AS lettre_a FROM users WHERE nom LIKE 'a%'
SELECT COUNT(*) AS lettre_b FROM users WHERE nom LIKE 'b%'
SELECT COUNT(*) AS lettre_c FROM users WHERE nom LIKE 'c%'
...
SELECT COUNT(*) AS lettre_z FROM users WHERE nom LIKE 'z%'

C'est possible avec UNION ? car là je n'obtiens pas ce que je souhaite avec un simple UNION entre chaque requete :cry:
Ou alors y-a-t-il une manière spéciale via PHP de récupérer le bon résultat de cette requete, s'il s'agit bien de cette requete.

Je vous remercie par avance de votre réponse.
@++

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

28 juin 2006, 20:45

En règle générale, je recommande aux utilisateurs qui ont un problème technique d'exposer ce qu'ils souhaitent obtenir plutôt qu'une façon d'exécuter une certaine action. En l'occurence, ce que tu cherches ce n'est pas vraiment comment faire des UNION et de COUNT(), j'imagine que tu veux le nombre d'utilisateurs pour chaque lettre de l'alphabet en initiale, n'est-ce pas ?

Pour cela tu peux utiliser GROUP BY, même sur un champs qui n'existe pas dans la base. Ce qu'il nous faut, c'est obtenir la première lettre du nom. Pour cela on peut utiliser la fonction SQL SUBSTRING() et l'utiliser avec GROUP BY. Par exemple:

Code : Tout sélectionner

SELECT SUBSTRING(nom FROM 1 FOR 1) AS initial, COUNT(*) as user_cnt FROM users GROUP BY initial
Pour info, j'utilise SUBSTRING() plutôt que LEFT() pour des raisons de compatibilité entre les bases de données. "user_cnt" est le diminutif de "user count". Attention à la collation de ta table, il se pourrait que "A" soit compté séparemment de "a". Si tu exécutes régulièrement cette requête, crée un nouveau champs "CHAR(1) NOT NULL BINARY" contenant l'initiale du nom en minuscule et indexe-le. La requête deviendra instantannée.

Eléphanteau du PHP | 19 Messages

28 juin 2006, 20:54

Merci Hubert. Désolé de ne pas avoir expliqué ce que je voulais faire clairement :?
Merci pour la solution, mais j'ai quand même une autre question: si le premier caractère du nom n'est pas une lettre ? je sais que théoriquement tous devraient être des lettres, mais il peut arriver qu'un utilisateur entre n'importe quoi (515db848) voire rien du tout dans le champ "nom".
Y-a-t-il un moyen de faire ça par la requete ou dois-je m'en occuper ultérieurement en passant un par un les résultats ?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

28 juin 2006, 21:27

SUBSTRING() extrait le premier caractère, donc lettres, chiffres, ponctuations, etc... n'importe quoi en fait :)

Eléphanteau du PHP | 19 Messages

28 juin 2006, 21:32

Oui d'accord, mais il n'y a donc pas de moyen direct de prendre en compte seulement les lettres en premier caractère ?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

28 juin 2006, 21:40

Mmh, je pense que tu peux essayer ça:

Code : Tout sélectionner

SELECT SUBSTRING(nom FROM 1 FOR 1) AS initial, COUNT(*) as user_cnt FROM users GROUP BY initial HAVING initial BETWEEN 'A' AND 'Z' OR initial BETWEEN 'a' AND 'z'
Ou tu peux remplacer la clause HAVING par une clause WHERE mais dans ce cas il faut remplacer "initial" par la fonction SUBSTRING() comme indiqué en haut.

Eléphanteau du PHP | 19 Messages

28 juin 2006, 21:43

Mmh, je pense que tu peux essayer ça:

Code : Tout sélectionner

SELECT SUBSTRING(nom FROM 1 FOR 1) AS initial, COUNT(*) as user_cnt FROM users GROUP BY initial HAVING initial BETWEEN 'A' AND 'Z' OR initial BETWEEN 'a' AND 'z'
Ou tu peux remplacer la clause HAVING par une clause WHERE mais dans ce cas il faut remplacer "initial" par la fonction SUBSTRING() comme indiqué en haut.
Vraiment PARFAIT ! c'est exactement ça !
Je te remercie énormément encore une fois !!

Je ne maitrise pas encore SQL comme il faut ...