Précédent   Forum des professionnels en informatique > Bases de données > MySQL > Requêtes
Requêtes Forum d'entraide sur les requêtes MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 13/01/2011, 18h45   #1
Membre habitué
 
Inscription : décembre 2008
Messages : 207
Détails du profil
Informations forums :
Inscription : décembre 2008
Messages : 207
Points : 121
Points : 121
Par défaut COUNT() et condition

Bonjour,

Il est nécessaire en premier lieu de consulter le schéma (simple) de la bdd concernée ; en pièce jointe. ( displayed_timestamp n'est plus un timestamp mais un datetime )

La requête doit :

- Récupérer tous les sites actif ( site_active = 1 )
- La catégorie du site
- La concaténation des formats de pub disponibles pour le site
- Le nombre de ligne ajoutées hier dans displayed pour chaque site

La requête fonctionne sans le dernier critère :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT 
site.*,
category.category_name,
COUNT(displayed.displayed_ip) AS display_count,
GROUP_CONCAT( pub_format.pub_format_name SEPARATOR ', ') AS pub_format_list
FROM site
LEFT JOIN category USING(category_id)
LEFT JOIN available_format USING(site_id)
LEFT JOIN pub_format USING(pub_format_id)
LEFT JOIN displayed USING(site_id)
WHERE site_active = 1
GROUP BY site.site_id
ORDER BY site_name
Mais si à la clause WHERE je rajoute :

Code :
displayed.displayed_timestamp BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND CURDATE()
Alors la requête ne me renvoie aucune ligne.
La table site ne comporte qu'une seule ligne, category, pub_format et available_format quelques unes, tandis que displayed est vide.

Je ne comprends pas le comportement de la requête complète.

Je voudrais dans la mesure du possible éviter SUM+IF , qui niveau performance laisse VRAIMENT à désirer, alors que la requête est déjà très lourde.

Où est le bins ? ^^
Images attachées
Type de fichier : png micro-cutted.png (58,9 Ko, 8 affichages)
Feng-Huang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/01/2011, 20h26   #2
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Citation:
La table site ne comporte qu'une seule ligne, category, pub_format et available_format quelques unes, tandis que displayed est vide.
Si tu rajoutes un filtre (dans la clause WHERE) limitant le résultat d'une table jointe en externe alors c'est comme si tu ne faisais pas de jointures externes mais en fait interne.
Comme displayed est vide la requête ne ramène rien.

Pour corriger, remontes le filtre dans la condition de jointures en utilisant ON à la place de USING (perso je n'aime pas trop USING mais bon ça n'est qu'un point de vu personnel, USING est bien dans la norme)

Code :
LEFT JOIN displayed d ON site.site_id = d.site_id AND d.displayed_timestamp BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND CURDATE()
Sinon, ton jeu de tests est trop petit pour t'en rendre compte mais ta requête est certainement fausse, en effet lorsqu'il y a regroupement il faut que toutes les colonnes non-agrégées soit présentes dans la clause GROUP BY. Sur la quasi-totalité des SGBD du marché ta requête renverrait une erreur de syntaxe, mysql est particulier là dessus, donc il faut lire absoluement :
http://cedric-duprez.developpez.com/...fier-group-by/
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/01/2011, 20h51   #3
Membre habitué
 
Inscription : décembre 2008
Messages : 207
Détails du profil
Informations forums :
Inscription : décembre 2008
Messages : 207
Points : 121
Points : 121
Tout d'abord merci de m'avoir répondu.

Ensuite, je ne savais pas qu'on pouvait mettre une clause au niveau de la jointure !
Y'a-t-il une différence entre la structure USING et ON ? (hormis que USING est franchement moins chiant fastidieux à écrire ET qu'on ne peut pas mettre de clause avec USING -avec MySQL en tout cas-).

Exact, j'ai oublié de mettre les colonnes dans le group by ( comme quoi Zend_Db_Select avait du bon en vérifiant l'intégrité des requêtes :p )

J'ai testé la requête suivante :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT 
site.site_name,
category.category_name,
COUNT(d.displayed_ip) AS display_count,
GROUP_CONCAT( pub_format.pub_format_name SEPARATOR ', ') AS pub_format_list
FROM site
LEFT JOIN category USING(category_id)
LEFT JOIN available_format USING(site_id)
LEFT JOIN pub_format USING(pub_format_id)
LEFT JOIN displayed d ON site.site_id = d.site_id AND d.displayed_timestamp BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND CURDATE()
WHERE site.site_active = 1
GROUP BY site.site_name,site.site_id,category.category_name
ORDER BY site_name
Elle semble fonctionner (je dis semble, car comme tu l'a remarquablement soulevé, je n'ai pas de jeu de données significatif)
Feng-Huang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/01/2011, 21h30   #4
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
USING permet de spécifier la jointure sur une colonne de chaque table lorsque le nom des colonnes de chaque table est identique (ce qui est plutôt une bonne pratique... pour permettre motamment USING ou NATURAL JOIN)
Je ne sais pas s'il est possible de joindre 2 tables sur plusieurs colonnes en utilisant USING, avec ON il n'y a aucun problème.

Comme je l'ai dit c'est un point de vu personnel, mais ce que j'aime avec ON c'est que ça force souvent à aliasser les tables, ce qui réduit l'écriture dans les clauses SELECT et WHERE, et a l'énorme avantage de clarifier les requêtes (j'aliasse toujours les colonnes qui ne sont pas communes même si ça n'est pas nécessaire)
Mais je ne pense pas que USING empêche les alias, c'est juste qu'ils sont moins souvent utilisés.

Après il est possible que je change d'avis dans le futur, car effectivement ça nécessite plus de touche clavier et par exemple je ne code jamais LEFT OUTER JOIN ou INNER JOIN

[EDIT] au fait je ne sais pas si j'étais vraiment clair sur mon explication avec la jointure externe et le filtre WHERE, au cas où, cinephil a publié un article sur son blog a ce sujet :
Jointure externe et condition de restriction
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/01/2011, 21h52   #5
Membre habitué
 
Inscription : décembre 2008
Messages : 207
Détails du profil
Informations forums :
Inscription : décembre 2008
Messages : 207
Points : 121
Points : 121
J'ai bien compris ton explication sur la clause WHERE.

Je te remercie pour toutes ces explications & précisions.
Feng-Huang est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h06.


 
 
 
 
Partenaires

Hébergement Web