Page 1 sur 1

Afficher la ligne avant et apres

Posté : 11 juil. 2014, 22:09
par Elie
Bonjour,

Je fais un classement de membre ou j'affiche la personne avant et apres eux ...
S'ils sont premier, j'affiche #2 et #3
S'ils sont dernier, j'affiche #last-1 et #last-2

Actuellement je le fais en PHP avec un tableau. 15 000 membres x 3 tableaux a fait des gros tableaux :)

Il y a t il moyen de simplifier cela dans une requete SQL ?

EDiT : Meme chose pour afficher la premiere et la derniere ligne d'une requete ?

Re: Afficher la ligne avant et apres

Posté : 13 juil. 2014, 21:04
par moogli
salut,

cela dépend du sgbd et de l'extension utilisée.

par exemple mysql propose la fonciton mysql_field_seek, couplé à un mysql_num_rowsy a moyen de faire ce que tu veux.

Maintenant l'extension mysqli étant déprécié il est préférable d'utiliser les équivalent mysqli
http://fr2.php.net/manual/en/mysqli-stmt.num-rows.php
http://fr2.php.net/manual/en/mysqli-stmt.data-seek.php
etc.

Pdo, ou l'exentension oci (oracke) ne permettent pas ce type de comportement.

La question qui vient a l'esprit est : pourquoi faire cela.
si tu affiche les infos d'une personne c'est relativement simple d'avoir avant et après.
pour les premières et dernière ligne en deux requêtes simple, en une seule simple avec une union et en limitant le nombre de ligne récupérées par chaque partie de l'union.

@+

Re: Afficher la ligne avant et apres

Posté : 13 juil. 2014, 21:20
par Elie
J'ai du choisir et je me suis orienté vers PDO ... Pas de bol.

Actuellement je recupere un array des 15 000 membres... Je trouve que ca fait lourd pour n'en garder que 3 lignes.
		// On recupere les points, les nb d'upload de chaque membres
		$aFichiers = $classement = array();
		$sql = "SELECT `id_fichier`, `film_id`, `release_id`, `date`, `filename`, `membre_id`, `pour`, `contre` FROM `tbl_fichier` WHERE `afficher` = 1 ORDER BY `date` ASC";
		$req = $connexion->query($sql);
		while($info = $req->fetch(PDO::FETCH_ASSOC)) {
			$classement['fichiers'][$info['membre_id']][] = 1;
			$classement['pour'][$info['membre_id']][] = $info['pour'];
			$classement['contre'][$info['membre_id']][] = $info['contre'];
			$aFichiers[$info['id_fichier']] = $info;
			$upload[$info['membre_id']][] = $info;
		}
Mon but serait de pouvoir donner l'iD du membre dans la requete en disant LiMiT -1, 3 :)

Ma requete peut être simplifié de toute facon avec des SUM...

Re: Afficher la ligne avant et apres

Posté : 13 juil. 2014, 22:06
par moogli
en sql tu peux le faire avec un union http://fr.openclassrooms.com/informatiq ... s-requetes

[mysql]
SELECT
`id_fichier`,
`film_id`,
`release_id`,
`date`,
`filename`,
`membre_id`,
`pour`,
`contre`
FROM `tbl_fichier`
WHERE `afficher` = 1
ORDER BY `date`
ASC
LIMIT 1

UNION ALL

SELECT
`id_fichier`,
`film_id`,
`release_id`,
`date`,
`filename`,
`membre_id`,
`pour`,
`contre`
FROM `tbl_fichier`
WHERE `afficher` = 1 AND membre_id = xxx
ORDER BY `date`
ASC

UNION ALL

SELECT
`id_fichier`,
`film_id`,
`release_id`,
`date`,
`filename`,
`membre_id`,
`pour`,
`contre`
FROM `tbl_fichier`
WHERE `afficher` = 1
ORDER BY `date`
DESC
LIMIT 1
[/mysql]

c'est un peu bourrin je trouve et pas terrible.

Je pense qu'il est plus intéressant de voir si tu ne peux pas utiliser directement une ou plusieurs procédures stockées ou fonction afin d'avoir les choses.
Problème : je en sais pas si l'on peux retourner un curseur avec mysql (Regarde de ce coté la http://dev.mysql.com/doc/refman/5.5/en/ ... m-A-4-1-19)

l'avantage de la fonction / procédure stockée c'est que tu peux insérer la logique que tu indique directement coté server et retourner les trois lignes qui t'intéresse.


@+

Re: Afficher la ligne avant et apres

Posté : 13 juil. 2014, 23:20
par Elie
Hello bon bah pour simplifier un peu le truc ... J'ai rajouté du COUNT, SUM, MIN et MAX pour obtenir plus que 3 array beaucoup légers.
		// On recupere les points, les nb d'upload de chaque membres
		$classement = array();
		$sql = "SELECT COUNT(`id_fichier`) as `nb_upload`, MIN(`id_fichier`) as `premier`, MAX(`id_fichier`) as `dernier`, `membre_id`, SUM(`pour`) as `total_pour`, SUM(`contre`) as `total_contre` FROM `tbl_fichier` WHERE `afficher` = 1 GROUP BY `membre_id` ORDER BY `membre_id` ASC";
		$req = $connexion->query($sql);
		while($info = $req->fetch(PDO::FETCH_ASSOC)) {
			$classement['fichiers'][$info['membre_id']] = $info['nb_upload'];
			$classement['pour'][$info['membre_id']] = $info['total_pour'];
			$classement['contre'][$info['membre_id']] = $info['total_contre'];
			if($info['membre_id'] == $row['id_membre']) $minMax = array($info['premier'], $info['dernier']);
		}
J'ai aussi simplifié le fait fait de retrouver la place du membre grace à keys() et array_search();
		// On fait les cumuls
		foreach($classement as $k => $v) {
			arsort($classement[$k]);
			$keys[$k] = array_keys($classement[$k]);
			$sakey[$k] = array_search($row['id_membre'], $keys[$k]);
		}
Et du coup avec mon MIN, MAX, je peux faire une seule requete avec un IN ($min, $max) ...

Je pense avoir réussi mon coup pour simplifier le chargement de la page !

http://www.subsynchro.com/voir-membre-subsynchro.html
La page c'est chargé en 0.289 secondes // PHP
La page c'est chargé en 24.813 secondes // JavaScript
Merci le temps de chargement des images ...