2 critères sur un ORDER BY

Eléphant du PHP | 372 Messages

18 juil. 2016, 07:11

Salut à tous j'ai une requete sql opérationnel mais j'aimerais lui rajouté un 3ème critère ds le ORDER BY:
- affiché tous les résultats "coup de coeur"
$sql .= " $sql .= " ORDER BY acti.id_actu AND id_user <> 999 DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage;;
J'ai donc une colonne "heart" ds ma bdd qui peut etre soit "vide" soit "ok".
Donc l'idée en gros ça doit donner d'abord les actu coup de coeur ensuite où l'id user est différent de 999 et puis le reste

Merci à vous

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

18 juil. 2016, 14:47

salut,

le peu de code que tu indiques n'est pas valide syntaxiquement.

je t'invite à regarder comment fonctionne la clause order by en SQL pour te rendre compte ton erreur et voir que ta demande peux être réaliser simplement.

je vois pas trop ce que vient faire de l'utilisateur, sachant que "hard coder" une telle valeur dans la requête me semble aller au devant d'emmerde (par plus de 998 utilisateurs ou alors les id commencent à 1000 ?).

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 372 Messages

18 juil. 2016, 16:28

En fait le <> 999 je m'en sert dans le sens ou j'ai beaucoup d'annonces avec cet id_user et je ne veut pas que celle ci soit afffiché en priorité mais bien ds l'ordre que j'ai cité ci dessus à savoir :

coup de coeur, les annonces différentes de id_user = 999 et enfin les annonces de id_user = 999

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

18 juil. 2016, 17:02

va falloir calculer un rang pour faire cela et ordonner dessus. tu as indiqué l'ordre.
Le plus simple d'une udf qui fait le calcul et retourne le rang (1, 2 ou 3 et tu ordonnes dessus.

PS : UDF : fonction crée par l'utilisateur http://dev.mysql.com/doc/refman/5.7/en/ ... edure.html (pour mysql)


@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 372 Messages

18 juil. 2016, 17:51

OucH ......

Quelque chose comme ne peut pas marcher je supose ?
$sql .= " ORDER BY loisirs.heart=heart AND loisirs.id_loisirs AND id_simply_user <> 999 DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage;;

Mammouth du PHP | 571 Messages

18 juil. 2016, 18:05

tu peux utiliser la structure conditionnelle IF qui évalue id_user !=999 . Dans ce cas on trie en fonction id_actu.Dans tous les autres cas on renvoie null( ou une colonne de la table)
$sql .= " $sql .= " ORDER BY IF(id_user <> 999,id_actu,NULL) DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage;
Une autre possibilité, sans utiliser if, est de faire la fusion entre la requête 1 où id_user !=999 et la requête 2 où id_user =999 en utilisant l'opérateur UNION
SELECT * FROM table WHERE id_user !=999
UNION
SELECT * FROM table WHERE id_user =999

Eléphant du PHP | 372 Messages

18 juil. 2016, 18:20

Oui mais dans l'exemple que tu a mis à quel moment ou fait référence à ma colonne heart

1/ heart
2 / différent de id_user 999
3/ et les id_user 999

Mammouth du PHP | 571 Messages

18 juil. 2016, 19:10

en reprenant ta colonne heart qui prend soit la valeur ok soit vide:
$sql="
SELECT * FROM loisirs WHERE heart='' OR heart='ok'
UNION
SELECT * FROM loisirs WHERE id_user !=999
UNION
SELECT * FROM loisirs WHERE id_user =999
LIMIT  ".intval(($page-1)*$parPage).", ".$parPage;
dans ce cas çi, tous les enregistrements heart seront retournés en premier, ensuite ceux dont id_user!=999 et enfin ceux dont l'id_user = 999

Eléphant du PHP | 372 Messages

18 juil. 2016, 19:17

Ah ok j'ai compris désolé après une journée du boulot j'ai du mal.
Par contre je souhaite gardé la structure de mes requete actuelle c'est à dire ainsi:
$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') .'\'';
	}

// Structuré cette requete avec le fameux UNION
$sql .= " ORDER BY loisirs.id_loisirs AND id_simply_user <> 999 DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage;;
		$req = $bdd->query($sql);
Donc comment rajouté ce Fameux SELECT UNION à mes requetes actuelles .

Merci encore

Mammouth du PHP | 571 Messages

19 juil. 2016, 11:46

Pour faire simple il me paraît plus évident d'évaluer ( avec une structure Case ... WHEN ou IF) les lignes qui satisfont aux conditions de tri à savoir (heart pas null, id_user !=999...).A chaque condition évaluée, il faut retourner un poids(un nombre qui donne l'ordre d'affichage) .

On remplace cette ligne:
$sql .= " ORDER BY loisirs.id_loisirs AND id_simply_user <> 999 DESC LIMIT ".intval(($page-1)*$parPage).", ".$parPage;;
par
$sql .= " ORDER BY CASE
					WHEN heart IS NOT NULL THEN 3
					WHEN id_simply_user != 999 THEN 2
					WHEN id_simply_user = 999 THEN 1
				  END DESC 
 LIMIT ".intval(($page-1)*$parPage).", ".$parPage;

Eléphant du PHP | 372 Messages

19 juil. 2016, 17:27

Alors après avoir testé ton bout de code, merci d'ailleurs quand même.

Le résultat attendu est assez étrange car la premiere est bien un différent de 999 mais après que des 999 et le heart disparu ....

Meme si je change l'ordre c'est toujours pareil en fait.

J'essai de faire donc dans l'odre:

- heart
- différent de 999
- 999

Quand heart est renseigné il a pour valeur : heart

Edit:
J'ai essayé ca mais sans suite:
// Priotité d'affichage
		$sql .= " ORDER BY CASE
		WHEN id_simply_user != 999 THEN 3
		WHEN id_simply_user = 999 THEN 2
		WHEN id_simply_user != 999 AND heart IS NOT NULL THEN 1
		END DESC 
	    LIMIT ".intval(($page-1)*$parPage).", ".$parPage;

Mammouth du PHP | 571 Messages

19 juil. 2016, 20:11

Le résultat attendu est assez étrange car la premiere est bien un différent de 999 mais après que des 999 et le heart disparu ....
tout dépend des données contenues dans tes tables.A priori toutes les annonces coup de coeur ont toutes été postées par l'utilisateur 999 ce qui expliquerait la disparition de ces annonces.

L'exemple suivant affichera en priorité tous les fruits dont le heart est 1 suivis de tous les fruits du user 999
CREATE TABLE fruit
(
id int auto_increment NOT NULL,
nom varchar(255) NOT NULL,
heart boolean DEFAULT 0,
user int(8),
PRIMARY KEY (id)
);

INSERT fruit VALUES(null,'abricot', 1, 800),
(null,'fraise', 1, 800),
(null,'pomme', 1, 801),
(null,'kiwi', 0, 999),
(null,'pêche', 0, 999),
(null,'orange', 0, 800),
(null,'poire', 1, 8001),
(null,'cerise', 1, 8001);
mysql> select * from  fruit order by case 
when heart = 1 then 3 
when user = 999 then 2 end desc;
+----+---------+-------+------+
| id | nom     | heart | user |
+----+---------+-------+------+
|  1 | abricot |     1 |  800 |
|  2 | fraise  |     1 |  800 |
|  3 | pomme   |     1 |  801 |
|  7 | poire   |     1 | 8001 |
|  8 | cerise  |     1 | 8001 |
|  4 | kiwi    |     0 |  999 |
|  5 | pêche   |     0 |  999 |
|  6 | orange  |     0 |  800 |
+----+---------+-------+------+

Eléphant du PHP | 372 Messages

19 juil. 2016, 20:58

C'est fou !!!
J'ai tester ton code c'est vrai ça marche le résultat attendu et exactement celui que je souhaite.
Mais de mon coté problème.
J'ai donc fait un echo de $sql pour voir ce qu'elle à dans le ventre et voilà :
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' ORDER BY CASE WHEN heart IS NOT NULL THEN 3 WHEN id_simply_user != 999 THEN 2 WHEN id_simply_user = 999 THEN 1 END DESC LIMIT 0, 15
Un peu long quand même, voici toutes les requetes de la page:
$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') .'\'';
	}

$sql .= " ORDER BY CASE
          WHEN heart IS NOT NULL THEN 3
          WHEN id_simply_user != 999 THEN 2
          WHEN id_simply_user = 999 THEN 1
          END DESC 
	 LIMIT ".intval(($page-1)*$parPage).", ".$parPage;
	 
	 echo $sql;
Pour le coup en bdd j'ai l'id_user ( 435 ) qui à une annonce en heart et pourtant je ne la vois pas....
Un truc de DINGUE !!!

Eléphant du PHP | 372 Messages

19 juil. 2016, 21:07

Bon
J'ai trouver fallait juste modifier cette ligne:
WHEN heart IS NOT NULL THEN 3
par
WHEN heart = 1 THEN 3

Eléphant du PHP | 372 Messages

20 juil. 2016, 22:48

Juste une dernière question mon code marche maintenant.
$sql .= " ORDER BY CASE
          WHEN heart = 1 THEN 3
          WHEN id_simply_user != 999 THEN 2
          WHEN id_simply_user = 999 THEN 1
          END DESC 
	 LIMIT ".intval(($page-1)*$parPage).", ".$parPage;
mais si je souhaite classé les annonces de l'utilisateur 999 par id_type loisir dois je faire ceci:
$sql .= " ORDER BY CASE
          WHEN heart = 1 THEN 3
          WHEN id_simply_user != 999 THEN 2
          WHEN id_simply_user = 999 ORDER by id_type_loisirs THEN 1
          END DESC 
	 LIMIT ".intval(($page-1)*$parPage).", ".$parPage;
Merci encore