Page 1 sur 1

Organiser une requete avec GROUP et ORDER

Posté : 11 juil. 2016, 21:05
par yoann38
Salut à tous.
J'ai essayer d'organiser ma requete afin de faire figuré chaque type et de selectioner les desnières rentrées de chaque type

J'ai donc tenté:
$sql .= "GROUP BY id_type_loisirs ORDER BY loisirs.id_loisirs  DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage ;;
Ca me prend bien chaque type mais pas les dernières entrées ....
Où est le problème selon vous ?
Merci ;)

EDIT:
Pour récupérer chaque type d'entrée
GROUP BY id_type_loisirs

et ORDER BY loisirs.id_loisirs
Pour essayer de les rangers du plus récent au plus ancien

Re: Organiser une requete avec GROUP et ORDER

Posté : 11 juil. 2016, 22:07
par Aureusms
As tu essayé de faire un
group by id_type_loisirs, id_loisirs
Le "group by" "écrase" les valeurs qui ne sont pas distincts.
Pour ma part, je compile les résultats dans un tableau en sortie pour faire en foreach par la suite.

Re: Organiser une requete avec GROUP et ORDER

Posté : 11 juil. 2016, 23:03
par yoann38
Malheuresement cette technique au niveau de la requete ne marche pas.
Je cherche à récupérer une entrée de chaque id_type_loisirs mais les dernières de chaque type ....

EDIT:
Si on met que le ORDER ca classe bien du plus récent au plus ancien
si je met le GROUP BY ca me selectionne bien un de chaque type mais les 2 ensemble ca ne marche pas.
Apres je ne vois pas trop la technique pour faire en sorte que cela fonctionne

Re: Organiser une requete avec GROUP et ORDER

Posté : 12 juil. 2016, 10:45
par Ryle
Bonjour,

Le GROUP BY ne fait que regrouper les éléments similaires présents dans le SELECT (équivalent en cela du distinct) et pour lesquels aucune fonction de groupe n'est appliquée (pas de count(), max(), avg() ...)

Pour ajouter une condition a ton GROUP BY, tu peux utiliser la clause HAVING pour inclure une clause sur la date. Tu peux aussi utiliser des sous-requêtes pour récupérer les informations dont tu as besoin.

Re: Organiser une requete avec GROUP et ORDER

Posté : 12 juil. 2016, 11:01
par moogli
salut,

a priori tu utilises mal le group by. vu que l'on a pas la clause select de la requête c'est une supposition.
group by s'utilise avec des fonctions de groupe (sum, max, avg etc.).

ce que tu souhaites c'est avoir les lignes de la table qui ont la dernier entrée pour chaque id_type_loisir. ne sachant pas comment savoir qu'elle est la dernière entrée (avec le create table cela aurait être plus simple ;) ) je suis parti sur le plus grand id de la table pour chaque type en considérant que la pk était bien un auto increment et qu'il n'y a pas d'opération ésotérique sur dessus ;) (c'est basique mais l'exemple est la).
Il te faut donc réduire le jeux de résultat en deux fois (avec un subselect).
-- create table
CREATE TABLE `yo` (
	id INT(11) NOT NULL AUTO_INCREMENT,
	id_type_loisir` INT(11) NOT NULL,
	id_loisirs INT(11) NOT NULL,
	PRIMARY KEY (id)
);
Jeux de données

Code : Tout sélectionner

"id" "id_type_loisir" "id_loisirs" "1" "1" "1" "2" "1" "2" "3" "1" "3" "4" "2" "4" "5" "2" "5" "6" "3" "6" "7" "3" "7" "8" "3" "8" "9" "3" "9" "10" "4" "10" "11" "4" "11"
La requête qui va bien
select id,id_type_loisir,id_loisirs from yo
where id in (select max(id) from yo group by id_type_loisir)
order by id_loisirs desc
Le résultat

Code : Tout sélectionner

"id" "id_type_loisir" "id_loisirs" "11" "4" "11" "9" "3" "9" "5" "2" "5" "3" "1" "3"
@+

Re: Organiser une requete avec GROUP et ORDER

Posté : 12 juil. 2016, 19:18
par yoann38
Salut à tous.
Alors en remettant renommant les variables correctement ça marche très bien j'ai testé ca dans PHPMYADMIN.
select id_loisirs,id_type_loisirs,id_loisirs from loisirs where id_loisirs in (select max(id_loisirs) from loisirs group by id_type_loisirs) order by id_loisirs desc
Par contre le fait de concaténé ma requete ( pas le choix )
J'ai du mal à combiner le tout.

Car mes requetes sont ainsi:
$sql = "SELECT * FROM `loisirs`  JOIN `regions` ON `regions`.`region_id` = `loisirs`.`id_region` WHERE `loisirs`.`date_fin_sortie` > NOW() AND `loisirs`.`valide` = 1";

$sql .= !empty($_REQUEST['region']) ? ' AND `regions`.`url` = "'.$_REQUEST['region'].'"' : NULL; // region
$sql .= !empty($_REQUEST['departement']) ? ' AND `loisirs`.`id_departements` = '.$_REQUEST['departement'] : NULL; 
$sql .= !empty($_REQUEST['loisir']) ? ' AND `loisirs`.`genre_loisir` = "'.$_REQUEST['loisir'].'"' : NULL; // loisir

// Recherche par date
if(!empty($du)) {}
$sql .= !empty($du) && !empty($au) ? " AND (DATE_FORMAT(`loisirs`.`date_debut_sortie`, '%Y-%m-%d') <= '".$du."' AND DATE_FORMAT(`loisirs`.`date_fin_sortie`, '%Y-%m-%d') >= '".$au."')" : NULL;


 // Recherche par ville
 $sql .= !empty($_REQUEST['ville']) ? ' AND `loisirs`.`city` = "'.getRealValue($_REQUEST['ville']).'"' : NULL;
		
// Recherche par salle
$sql .= !empty($_REQUEST['manufacturer']) ? ' AND `loisirs`.`manufacturer` = "'.getRealValue($_REQUEST['manufacturer'], 'manufacturer').'"' : NULL;

// Et enfin mon problème actuel :)  
// Si aucun loisir n'est renseigné on affiche chaque type de loisir
if (empty($_REQUEST['loisir']) && empty($_GET['page']) && empty($_REQUEST['departement'])) {
$sql .= "GROUP BY id_type_loisirs ORDER BY loisirs.id_loisirs  DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage ;;
}else {
$sql .= " ORDER BY loisirs.id_loisirs  DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage ;;
}
J'ai la bonne requete mais étant donné que je commence par le GROUP ... comment arrangé le tout, svp
Merci encore

Re: Organiser une requete avec GROUP et ORDER

Posté : 13 juil. 2016, 10:06
par moogli
modifie ta requête pour ne retourner que l'id_loisirs
ensuite select * from loisirs where id_loisir in ( $sql )

l'opérateur ternaire c'est le mal ;)
oui ça simplifie l'écriture mais ça même à des choses un peu foireuse comme null en défaut ($sql .= null ...). Et ce n'est pas clair a lire (gymnastique psychique alors que l'on peu faire un truc plus naturel).

Je ferais un truc dans le genre.
<?php
$sql = 'SELECT * FROM loisirs WHERE loisirs.date_fin_sortie > NOW() AND loisirs.valide = 1';
// region
if(!empty($_REQUEST['region'])){
  // FIXME : sql injectin spoted
  $sql .= ' AND regions.url = \''.$_REQUEST['region'].'\'' ;
}
if(!empty($_REQUEST['departement'])){
  $sql .=  ' AND loisirs.id_departements = '.$_REQUEST['departement'];
}

if(!empty($_REQUEST['loisir']) ){
  // FIXME : sql injectin spoted
  $sql .=  ' AND loisirs.genre_loisir = \''.$_REQUEST['loisir'].'\'' ; // loisir
}

// Recherche par date
// FIXME : $du et $au n'existe pas ici ;)
// FIXME : sql injectin spoted
if(!empty($du) && !empty($au)) {
  $sql .= ' AND (DATE_FORMAT(loisirs.date_debut_sortie, \'%Y-%m-%d\') <= \''.$du.'\' AND DATE_FORMAT(loisirs.date_fin_sortie, \'%Y-%m-%d\') >= \''.$au.'\')';
}

 // Recherche par ville
if(!empty($_REQUEST['ville'])) {
  $sql .= ' AND loisirs.city = \''. getRealValue($_REQUEST['ville']). '\'';
}

// Recherche par salle
if(!empty($_REQUEST['manufacturer'])){
  $sql .= ' AND loisirs.manufacturer = \''. getRealValue($_REQUEST['manufacturer'] , 'manufacturer') .'\'';
}

// Si aucun loisir n'est renseigné on affiche chaque type de loisir
// FIXME : $page est surement définie avant ?
if (empty($_REQUEST['loisir']) && empty($_GET['page']) && empty($_REQUEST['departement'])) {
  $sql .= ' GROUP BY id_type_loisirs ORDER BY loisirs.id_loisirs';
}else {
  $sql .= ' ORDER BY loisirs.id_loisirs';
}
$sql .= ' DESC LIMIT '.intval(($page-1)*$parPage).', '.$parPage ;

// la première partie de la requête permet de filtrer et de grouper, celle ci d'avoir les données
$sqlFinal = 'select * from loisirs JOIN regions ON regions.region_id = loisirs.id_region where loisirs in ('.$sql.')';

// exec
@+

Re: Organiser une requete avec GROUP et ORDER

Posté : 13 juil. 2016, 17:48
par yoann38
C'est pas mal :p
Merci pour le coup de pouce.
J'ai corrigé la première requete car tu avais oublié de mettre le JOIN donc forcément ...

Par contre j'ai oublié de préciser ( un peu bete pour le coup aussi faut dire ) le but de ma requete c'est qu'elle doit agir si c'est un département, une région ou une ville.

J'ai donc maintenant niveau requete:
$sql = 'SELECT * FROM loisirs JOIN `regions` ON `regions`.`region_id` = `loisirs`.`id_region` WHERE  loisirs.date_fin_sortie > NOW() AND loisirs.valide = 1';
	// region
	if(!empty($_REQUEST['region'])){
	  // FIXME : sql injectin spoted
	  $sql .= ' AND regions.url = \''.$_REQUEST['region'].'\'' ;
	}
	if(!empty($_REQUEST['departement'])){
	  $sql .=  ' AND loisirs.id_departements = '.$_REQUEST['departement'];
	}
	
	if(!empty($_REQUEST['loisir']) ){
	  // FIXME : sql injectin spoted
	  $sql .=  ' AND loisirs.genre_loisir = \''.$_REQUEST['loisir'].'\'' ; // loisir
	}
	
	// Recherche par date
	// FIXME : $du et $au n'existe pas ici ;)
	// FIXME : sql injectin spoted
	if(!empty($du) && !empty($au)) {
	  $sql .= ' AND (DATE_FORMAT(loisirs.date_debut_sortie, \'%Y-%m-%d\') <= \''.$du.'\' AND DATE_FORMAT(loisirs.date_fin_sortie, \'%Y-%m-%d\') >= \''.$au.'\')';
	}
	
	 // Recherche par ville
	if(!empty($_REQUEST['ville'])) {
	  $sql .= ' AND loisirs.city = \''. getRealValue($_REQUEST['ville']). '\'';
	}
	
	// Recherche par salle
	if(!empty($_REQUEST['manufacturer'])){
	  $sql .= ' AND loisirs.manufacturer = \''. getRealValue($_REQUEST['manufacturer'] , 'manufacturer') .'\'';
	}


  // Si aucun loisir n'est renseigné on affiche chaque type de loisir
		// FIXME : $page est surement définie avant ?
		if (empty($_REQUEST['loisir']) && empty($_GET['page']) && empty($_REQUEST['departement'])) {
		  $sql .= ' GROUP BY id_type_loisirs ORDER BY loisirs.id_loisirs';
		}else {
		  $sql .= ' ORDER BY loisirs.id_loisirs';
		}
		$sql .= ' DESC LIMIT '.intval(($page-1)*$parPage).', '.$parPage ;
		
		// la première partie de la requête permet de filtrer et de grouper, celle ci d'avoir les données
		$sqlFinal = 'select * from loisirs JOIN regions ON regions.region_id = loisirs.id_region where loisirs in ('.$sql.')';
EDIT:
J'ai tester dans PHPMYADMIN ceci ca marche mais pas dans ma page ...
SELECT *
FROM loisirs
WHERE id_loisirs
IN (

SELECT max( id_loisirs )
FROM loisirs
WHERE city = 'grenoble'
GROUP BY id_type_loisirs
)
ORDER BY id_loisirs DESC
LIMIT 0 , 30

Re: Organiser une requete avec GROUP et ORDER

Posté : 18 juil. 2016, 15:18
par moogli
EDIT:
J'ai tester dans PHPMYADMIN ceci ca marche mais pas dans ma page ...
ça aide pas trop, qu'est ce qui ne fonctionne pas ?
tu exécutes bien la requête ?
tu affiches bien le résultat quelque part ?

@+

Re: Organiser une requete avec GROUP et ORDER

Posté : 27 juil. 2016, 21:10
par yoann38
Donc en tapant la requete dans PHPMYADMIN ca marche nikel ;)

Mais ca bloque sur ma page.
J'ai du m'embrouiller dans mes $sql .

Donc actuellement ma page est comme ceci sur la partie concernée:
$sql = 'SELECT * FROM loisirs JOIN `regions` ON `regions`.`region_id` = `loisirs`.`id_region` WHERE  loisirs.date_fin_sortie > NOW() AND loisirs.valide = 1';
  // region
  if(!empty($_REQUEST['region'])){
    // FIXME : sql injectin spoted
    $sql .= ' AND regions.url = \''.$_REQUEST['region'].'\'' ;
  }
  if(!empty($_REQUEST['departement'])){
    $sql .=  ' AND loisirs.id_departements = '.$_REQUEST['departement'];
  }
  
  if(!empty($_REQUEST['loisir']) ){
    // FIXME : sql injectin spoted
    $sql .=  ' AND loisirs.genre_loisir = \''.$_REQUEST['loisir'].'\'' ; // loisir
  }
  

  // FIXME : sql injectin spoted
  if(!empty($du) && !empty($au)) {
    $sql .= ' AND (DATE_FORMAT(loisirs.date_debut_sortie, \'%Y-%m-%d\') <= \''.$du.'\' AND DATE_FORMAT(loisirs.date_fin_sortie, \'%Y-%m-%d\') >= \''.$au.'\')';
  }
  
   // Recherche par ville
  if(!empty($_REQUEST['ville'])) {
    $sql .= ' AND loisirs.city = \''. getRealValue($_REQUEST['ville']). '\'';
  }



	$req = $bdd->query($sql);


		$nbre_annonces_par_page = 10;
		$nbre_pages_max_gauche_et_droite = 4;
		$last_page = ceil($nb / $nbre_annonces_par_page);
		if(isset($_GET['page']) && is_numeric($_GET['page'])){
		$page_num = $_GET['page'];
		} else {
		$page_num = 1;
		}
		if($page_num < 1){
		$page_num = 1;
		} else if($page_num > $last_page) {
		$page_num = $last_page;
		}
		$limit = 'LIMIT '.($page_num - 1) * $nbre_annonces_par_page. ',' . $nbre_annonces_par_page;
		$pagination = '';
		if($last_page != 1){
		if($page_num > 1){
		$previous = $page_num - 1;
		$pagination .= '<a href="'.$valeur_paginate.($previous > 1 ? '-page-'.$previous : null).'.html" class="page" data-page="'.$previous.'" data-du="'.$du.'" data-au="'.$au.'"><i class="fa fa-angle-left"></i></a> &nbsp; &nbsp;';
		for($i = $page_num - $nbre_pages_max_gauche_et_droite; $i < $page_num; $i++){
		if($i > 0){
		$pagination .= '<a href="'.$valeur_paginate.($i > 1 ? '-page-'.$i : null).'.html" class="page" data-page="'.$i.'" data-du="'.$du.'" data-au="'.$au.'">'.$i.'</a> &nbsp;';
		}
		}
		}
		$pagination .= '<span class="active">'.$page_num.'</span>&nbsp;';
		for($i = $page_num+1; $i <= $last_page; $i++){	
		$pagination .= '<a href="'.$valeur_paginate.'-page-'.$i.'.html" class="page" data-page="'.$i.'" data-du="'.$du.'" data-au="'.$au.'">'.$i.'</a> ';
		if($i >= $page_num + $nbre_pages_max_gauche_et_droite){
		break;
		}
		}
		if($page_num != $last_page){
		$next = $page_num + 1;
		$pagination .= '<a href="'.$valeur_paginate.'-page-'.$next.'.html" class="page" data-page="'.$next.'" data-du="'.$du.'" data-au="'.$au.'"><i class="fa fa-angle-right"></i></a> ';
		}
		}

		// Si aucun loisir n'est renseigné on affiche chaque type de loisir
    	// FIXME : $page est surement définie avant ?
		if (empty($_REQUEST['loisir']) && empty($_GET['page']) && empty($_REQUEST['departement'])) {
		  $sql .= ' GROUP BY id_type_loisirs ORDER BY loisirs.id_loisirs';
		}else {
		  $sql .= ' ORDER BY loisirs.id_loisirs';
		}
		$sql .= ' DESC LIMIT '.intval(($page-1)*$parPage).', '.$parPage ;
		
		// la première partie de la requête permet de filtrer et de grouper, celle ci d'avoir les données
		$sqlFinal = 'select * from loisirs JOIN regions ON regions.region_id = loisirs.id_region where loisirs in ('.$sql.')';
		
		echo $sqlFinal;
		
		$req = $bdd->query($sql);

L'echo de la requete pour le coup par exemple avec la région rhone-alpes renvoi:
select * from loisirs JOIN regions ON regions.region_id = loisirs.id_region where loisirs in (SELECT * FROM loisirs JOIN `regions` ON `regions`.`region_id` = `loisirs`.`id_region` WHERE loisirs.date_fin_sortie > NOW() AND loisirs.valide = 1 AND regions.url = 'rhone-alpes' GROUP BY id_type_loisirs ORDER BY loisirs.id_loisirs DESC LIMIT 0, 10)

Re: Organiser une requete avec GROUP et ORDER

Posté : 28 juil. 2016, 09:58
par moogli
tu as testé cette requete dans phpmyadmin ?
cette partie me semble louche ; where loisirs in (SELECT
tu l'as testée tel quel avec PMA ? (il couine pas ?)
loisirs semble être une table et pas une colonne du coup ta requête me semble foireuse.
tu as recopié un peu rapidement ce que j'ai mis ?
c'est id_loisirs in ( la sous requête qui retourne les plus grand id pour chaque prédicat calculé avant).

@+

Re: Organiser une requete avec GROUP et ORDER

Posté : 28 juil. 2016, 16:18
par yoann38
Salut,
Alors oui loisirs est bien une table et non une colonne ceci dit.
Je pense avoir fait scrupuleusement ce que tu m'as indiqué

Dans PMA, une fois la requete éxécuté j'ai bien une erreur:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 2

Je pense que ça na rien avoir .... dur dur ...

Re: Organiser une requete avec GROUP et ORDER

Posté : 02 août 2016, 11:15
par Ryle
Bonjour,

Le order by et le limit ne devraient pas être dans la sous-requête. Ta parenthèse devrait se fermer avant d'utiliser ces instructions :)

A tester également, au lieu d'une sous requête, une jointure vers la même table peut parfois être plus performante (ça dépend du moteur, des indexes...). En reprenant le jeu de donnée proposé par moogli, on aurait quelque chose du genre :
SELECT y1.*
FROM yo y1 LEFT JOIN yo y2
 ON y1.id_type_loisir = y2.id_type_loisir AND y1.id < y2.id
WHERE y2.id IS NULL;