Requete avec distinct sur mysql

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Requete avec distinct sur mysql

par Hubert Roksor » 19 nov. 2007, 22:36

No prob' on est là pour ça. Pour info, les sous-requêtes dans la clause FROM sont généralement appelée "tables dérivées". C'est comme une table temporaire, mais plus pratique.

par Gico » 19 nov. 2007, 19:53

Voila j'ai pris le temps de regarder tous ça, honnetement je suis bluffé ça fonctionne parfaitement, avec quelques adaptations, j'affiche ce que je souhaitais, maintenant j'avoue que je ne suspectais pas l'existence de la moitiée des fonctions que tu utilise, ça m'ouvre des perspectives. Je vais faire honneur au temps que tu m'a accordé et au savoir que tu dispenses si genereusement en etudiant ça de très prés.

Merci encore

par Gico » 19 nov. 2007, 14:34

je souhaitais deja te remercier avant d'être passé a l'application de tes conseils, car ça va me prendre un peu de temp, je vais etudier ça attentivement.

par Hubert Roksor » 19 nov. 2007, 10:27

Ok, donc pour l'exemple on va dire que tu veux récupérer toutes les photos du groupe 1 et la photo la plus récente des autres groupes. SQL ne permet pas de faire un peu de GROUP BY par ci et un peu de "je récupère tout" par là, mais ce n'est pas un problème : il suffit de récupérer la première moitié dans une requête puis le reste dans une autre. Mieux encore, on peut utiliser UNION pour récupérer les deux résultats l'un à la suite de l'autre.

Pour en revenir à la requête en question, il n'existe malheureusement pas dans SQL de méchanisme pour récupérer l'enregistrement possédant le plus grand X pour chaque groupe. Ça ne veut pas dire que c'est impossible, c'est juste un peu plus long à écrire.

Ce que SQL permet, c'est de récupérer la plus grande valeur de X pour chaque groupe. Par exemple:

Code : Tout sélectionner

SELECT id_photo_groupe, MAX(date_in) AS date_in FROM photos WHERE id_photo_groupe <> 1 GROUP BY id_photo_groupe
J'appellerai ce résultat tmp1. On a donc pour chaque groupe la date la plus récente. On peut savoir à quel(s) enregistrement(s) chaque date de chaque groupe correspond à l'aide d'une jointure. Et puisqu'il est théoriquement possible que plusieurs photos soient uploadées au même moment, on ne récupère que le numéro d'enregistrement id_photo de chaque date de chaque groupe

Code : Tout sélectionner

SELECT MAX(p1.id_photo) AS id_photo FROM ( SELECT id_photo_groupe, MAX(date_in) AS date_in FROM photos WHERE id_photo_groupe <> 1 GROUP BY id_photo_groupe ) AS tmp1 JOIN photos p1 USING (id_photo_groupe, date_in) GROUP BY p1.id_photo_groupe
Ce qui nous donne le résultat tmp2, correspondant à l'identifiant id_photo de chaque groupe. Maintenant que l'on a un identifiant et que l'on n'a plus à grouper les résultat, on peut récupérer le reste des informations dont on a besoin à l'aide d'une dernière jointure, ce qui nous donne toutes les données de la photo la plus récente dans chaque groupe.

Code : Tout sélectionner

SELECT p2.* FROM ( SELECT MAX(p1.id_photo) AS id_photo FROM ( SELECT id_photo_groupe, MAX(date_in) AS date_in FROM photos WHERE id_photo_groupe <> 1 GROUP BY id_photo_groupe ) AS tmp1 JOIN photos p1 USING (id_photo_groupe, date_in) GROUP BY p1.id_photo_groupe ) AS tmp2 JOIN photos p2 USING (id_photo)
La dernière étape qui consiste à adjoindre les informations de toutes les photos du groupe sélectionné, ce qui nous donne

Code : Tout sélectionner

( SELECT * FROM photos WHERE id_photo_groupe = 1 ) UNION ALL ( SELECT p2.* FROM ( SELECT MAX(p1.id_photo) AS id_photo FROM ( SELECT id_photo_groupe, MAX(date_in) AS date_in FROM photos WHERE id_photo_groupe <> 1 GROUP BY id_photo_groupe ) AS tmp1 JOIN photos p1 USING (id_photo_groupe, date_in) GROUP BY p1.id_photo_groupe ) AS tmp2 JOIN photos p2 USING (id_photo) )
Pour des questions de performance, n'oublie pas d'ajouter un index sur (id_photo_groupe,date_in)

Code : Tout sélectionner

CREATE INDEX date_par_groupe ON photos (id_photo_groupe, date_in)

par Gico » 19 nov. 2007, 00:23

Code : Tout sélectionner

CREATE TABLE `photos` ( `id_photo` int(11) NOT NULL auto_increment, `id_photo_groupe` smallint(6) unsigned default '0', `photo_nm` varchar(80) NOT NULL, `photo_titre` varchar(150) NOT NULL, `photo_txt` tinytext, `photo_auteur` varchar(60) default NULL, `date` date default NULL, `date_in` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`id_photo`) ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;

par Truc » 19 nov. 2007, 00:21

Exporter de phpMyAdmin regarde le point sur "Exporter"

et poster un truc qui ressemble à

Code : Tout sélectionner

CREATE TABLE machin ( champ1 INT; )

par Gico » 19 nov. 2007, 00:11

je n'ai pas encore fais la requete je ne sais pas encore par quel bout la prendre. la table est simple: disons que j'ai 10 photos, 6 dans la categorie 1, et 4 dans la categorie 2. Je voudrais que la requete puisse extraire les 6 de la categorie 1 et seulement la première de la catégorie 2 avec un order, je souhaite ensuite les classer par le champ date.

par Hubert Roksor » 18 nov. 2007, 23:15

Concernant le schéma, il te faut l'exporter sous phpMyAdmin (ou exécuter SHOW CREATE TABLE) et poster le résultat ici.
afficher que la premiere photo de ces themes
Comment définis-tu "premier" ? Y a-t'il une colonne servant à classer les photos ?

par Gico » 18 nov. 2007, 22:49

bon... shema alors, en tous cas je vais essyer d'etre plus clair

table photo :

id_photo, photo_nom, categorie_id...

je veux afficher tous ça, donc requete

$requete = " select * from photo";

boucle pour afficher tous les resultats... mais en fait je voudrais afficher toutes les photos qui appartiennent à la categorie_id= 1, mais pour les autres categories je ne voudrais afficher dans la page que la premiere photo de cette categorie.
Autrement dit la categorie 1 correspond en fait aux photos entrées sans thème particulier alors que les autres categories correspondent a des groupes de photo sur un thème, je ne souhaite donc afficher que la premiere photo de ces themes (un clic dessus ouvrira une autre page avec seulement les photos de ce theme)
un sorte de "distinct "sur la catégorie mais valable uniquement sur les categories !=1
j'espere avoir ete plus clair.
merci

par Hubert Roksor » 18 nov. 2007, 19:20

Tu n'as pas posté le schéma de ta table.

Il y a deux façons de répondre à ta question, à partir du schéma et à partir d'une boule de crystal, et ma boule de crystal est en révision...

Requete avec distinct sur mysql

par Gico » 18 nov. 2007, 19:01

Bonjour
je voudrais construire une requete selective, mais j'ai un peu de mal.

le principe : j'ai une liste de photos, toutes regroupées dans des sous-categories( la sous-categorie est un champ de la table "photo".
je voudrais afficher une liste de ses photos, avec TOUTES les photos de la categorie 1, et seulement la première des categorie 2, 3, 4...-donc avec un LIMIT 1 juste pour les categories superieures à 1.
Est-ce possible en une seule requete ?
merci