Comment obtenir l’enregistrement suivant / précédent dans MySQL?

Disons que j’ai des enregistrements avec identifiants 3,4,7,9 et que je veux pouvoir passer de l’un à l’autre en naviguant via les liens suivant / précédent. Le problème est que je ne sais pas comment extraire un enregistrement avec l’identifiant le plus proche.

Donc, quand j’ai un enregistrement avec ID 4, je dois pouvoir extraire le prochain enregistrement existant, qui serait 7. La requête ressemblerait probablement à quelque chose

SELECT * FROM foo WHERE id = 4 OFFSET 1 

Comment puis-je récupérer l’enregistrement suivant / précédent sans récupérer l’ensemble du résultat et l’itération manuelle?

J’utilise MySQL 5.

prochain:

 select * from foo where id = (select min(id) from foo where id > 4) 

précédent:

 select * from foo where id = (select max(id) from foo where id < 4) 

En plus de la solution de cemkalyoncu :

prochain enregistrement:

 SELECT * FROM foo WHERE id > 4 ORDER BY id LIMIT 1; 

enregistrement précédent:

 SELECT * FROM foo WHERE id < 4 ORDER BY id DESC LIMIT 1; 

edit: Comme cette réponse a reçu quelques commentaires récemment, je tiens vraiment à souligner le commentaire que j'ai fait plus tôt concernant la compréhension du fait qu'une colonne de clé primaire ne doit pas être considérée comme une colonne à sortinger, car MySQL ne garantit pas , les valeurs sont nécessairement ajoutées ultérieurement.

Si vous ne vous souciez pas de cela, et que vous avez simplement besoin de l'enregistrement avec un id supérieur (ou inférieur), cela suffira. N'utilisez simplement pas ceci comme moyen de déterminer si un enregistrement est effectivement ajouté ultérieurement (ou plus tôt). Au lieu de cela, envisagez d'utiliser une colonne datetime pour sortinger, par exemple.

Toutes les solutions ci-dessus nécessitent deux appels à la firebase database. Le code SQL ci-dessous combine deux instructions SQL en une.

 select * from foo where ( id = IFNULL((select min(id) from foo where id > 4),0) or id = IFNULL((select max(id) from foo where id < 4),0) ) 
 SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1 

J’essayais de faire quelque chose de similaire, mais j’avais besoin des résultats classés par date car je ne peux pas compter sur le champ ID comme colonne sortingable. Voici la solution que j’ai trouvée.

D’abord, nous trouvons l’index de l’enregistrement souhaité dans la table, lorsqu’il est sortingé comme nous le souhaitons:

 SELECT row FROM (SELECT @rownum:=@rownum+1 row, a.* FROM articles a, (SELECT @rownum:=0) r ORDER BY date, id) as article_with_rows WHERE id = 50; 

Ensuite, décrémentez le résultat de 2 en le mettant dans l’instruction limite. Par exemple, ce qui précède a rapporté 21 pour moi, donc je cours:

 SELECT * FROM articles ORDER BY date, id LIMIT 19, 3 

Vous donne votre enregistrement principal avec ses enregistrements suivants et précédents en fonction de votre ordre indiqué.

J’ai essayé de le faire en tant qu’appel de firebase database unique, mais je n’ai pas pu obtenir que l’instruction LIMIT prenne une variable parmi ses parameters.

Essayez cet exemple.

 create table student(id int, name varchar(30), age int); insert into student values (1 ,'Ranga', 27), (2 ,'Reddy', 26), (3 ,'Vasu', 50), (5 ,'Manoj', 10), (6 ,'Raja', 52), (7 ,'Vinod', 27); SELECT name, (SELECT name FROM student s1 WHERE s1.id < s.id ORDER BY id DESC LIMIT 1) as previous_name, (SELECT name FROM student s2 WHERE s2.id > s.id ORDER BY id ASC LIMIT 1) as next_name FROM student s WHERE id = 7; 

Note: Si la valeur n’est pas trouvée, alors elle retournera null .

Dans l’exemple ci-dessus, la valeur précédente sera Raja et la valeur Next sera nulle car il n’y a pas de valeur suivante.

Rang suivante

 SELECT * FROM `foo` LIMIT number++ , 1 

Rangée précédente

 SELECT * FROM `foo` LIMIT number-- , 1 

échantillon prochaine rangée

 SELECT * FROM `foo` LIMIT 1 , 1 SELECT * FROM `foo` LIMIT 2 , 1 SELECT * FROM `foo` LIMIT 3 , 1 

échantillon rangée précédente

 SELECT * FROM `foo` LIMIT -1 , 1 SELECT * FROM `foo` LIMIT -2 , 1 SELECT * FROM `foo` LIMIT -3 , 1 SELECT * FROM `foo` LIMIT 3 , 1 SELECT * FROM `foo` LIMIT 2 , 1 SELECT * FROM `foo` LIMIT 1 , 1 

Grâce à l’approche de @Dan, vous pouvez créer des JOIN. Utilisez simplement une variable @ différente pour chaque sous-requête.

 SELECT current_row.row, current_row.id, previous_row.row, previous_row.id FROM ( SELECT @rownum:=@rownum+1 row, a.* FROM articles a, (SELECT @rownum:=0) r ORDER BY date, id ) as current_row LEFT JOIN ( SELECT @rownum2:=@rownum2+1 row, a.* FROM articles a, (SELECT @rownum2:=0) r ORDER BY date, id ) as previous_row ON (current_row.id = previous_row.id) AND (current_row.row = previous_row.row - 1) 

J’ai eu le même problème que Dan, j’ai donc utilisé sa réponse et l’ai améliorée.

Sélectionnez d’abord l’index de ligne, rien de différent ici.

 SELECT row FROM (SELECT @rownum:=@rownum+1 row, a.* FROM articles a, (SELECT @rownum:=0) r ORDER BY date, id) as article_with_rows WHERE id = 50; 

Utilisez maintenant deux requêtes distinctes. Par exemple, si l’index de ligne est 21, la requête pour sélectionner l’enregistrement suivant sera:

 SELECT * FROM articles ORDER BY date, id LIMIT 21, 1 

Pour sélectionner l’enregistrement précédent, utilisez cette requête:

 SELECT * FROM articles ORDER BY date, id LIMIT 19, 1 

Gardez à l’esprit que pour la première ligne (l’index de ligne est 1), la limite passera à -1 et vous obtiendrez une erreur MySQL. Vous pouvez utiliser une instruction if pour empêcher cela. Il suffit de ne rien sélectionner, car il n’y a aucun enregistrement précédent de toute façon. Dans le cas du dernier enregistrement, il y aura la prochaine rangée et il n’y aura donc aucun résultat.

Gardez également à l’esprit que si vous utilisez DESC pour commander, au lieu de ASC, les requêtes pour sélectionner les lignes suivantes et précédentes sont toujours les mêmes, mais commutées.

Comment obtenir l’enregistrement suivant / précédent dans MySQL & PHP?

Mon exemple est de ne récupérer que l’id

 function btn_prev(){ $id = $_POST['ids']; $re = mysql_query("SELECT * FROM table_name WHERE your_id < '$id' ORDER BY your_id DESC LIMIT 1"); if(mysql_num_rows($re) == 1) { $r = mysql_fetch_array($re); $ids = $r['your_id']; if($ids == "" || $ids == 0) { echo 0; } else { echo $ids; } } else { echo 0; } } function btn_next(){ $id = $_POST['ids']; $re = mysql_query("SELECT * FROM table_name WHERE your_id > '$id' ORDER BY your_id ASC LIMIT 1"); if(mysql_num_rows($re) == 1) { $r = mysql_fetch_array($re); $ids = $r['your_id']; if($ids == "" || $ids == 0) { echo 0; } else { echo $ids; } } else { echo 0; } } 

Ceci est une solution universelle pour les conditions avec plus de résultats identiques.

 < ?php $your_name1_finded="somethnig searched"; //$your_name1_finded must be finded in previous select $result = db_query("SELECT your_name1 FROM your_table WHERE your_name=your_condition ORDER BY your_name1, your_name2"); //Get all our ids $i=0; while($row = db_fetch_assoc($result)) { //Loop through our rows $i++; $current_row[$i]=$row['your_name1'];// field with results if($row['your_name1'] == $your_name1_finded) {//If we haven't hit our current row yet $yid=$i; } } //buttons if ($current_row[$yid-1]) $out_button.= "BUTTON_PREVIOUS"; if ($current_row[$yid+1]) $out_button.= "BUTTON_NEXT"; echo $out_button;//display buttons ?> 

Ici, nous avons un moyen de récupérer les enregistrements précédents et suivants en utilisant une seule requête MySQL. Où 5 est l’identifiant de l’enregistrement en cours.

 select * from story where catagory=100 and ( id =(select max(id) from story where id < 5 and catagory=100 and order by created_at desc) OR id=(select min(id) from story where id > 5 and catagory=100 order by created_at desc) ) 

Il existe une autre astuce que vous pouvez utiliser pour afficher les colonnes des lignes précédentes, en utilisant n’importe quel ordre, en utilisant une variable similaire à l’astuce @row:

 SELECT @prev_col_a, @prev_col_b, @prev_col_c, @prev_col_a := col_a AS col_a, @prev_col_b := col_b AS col_b, @prev_col_c := col_c AS col_c FROM table, (SELECT @prev_col_a := NULL, @prev_col_b := NULL, @prev_col_c := NULL) prv ORDER BY whatever 

Apparemment, les colonnes select sont évaluées dans l’ordre, cela va donc d’abord sélectionner les variables enregistrées, puis mettre à jour les variables sur la nouvelle ligne (en les sélectionnant dans le processus).

NB: Je ne suis pas sûr que ce soit un comportement défini, mais je l’ai utilisé et ça marche.

Si vous voulez next_id plus d’un id à votre requête et obtenir next_id pour tous …

Atsortingbuez cur_id dans votre champ de sélection, puis alimentez-le en sous-requête pour obtenir next_id dans le champ de sélection. Et puis sélectionnez juste next_id .

En utilisant la réponse longneck à calc next_id :

 select next_id from ( select id as cur_id, (select min(id) from `foo` where id>cur_id) as next_id from `foo` ) as tmp where next_id is not null; 
 CREATE PROCEDURE `pobierz_posty`(IN iduser bigint(20), IN size int, IN page int) BEGIN DECLARE start_element int DEFAULT 0; SET start_element:= size * page; SELECT DISTINCT * FROM post WHERE id_users .... ORDER BY data_postu DESC LIMIT size OFFSET start_element END 

Si vous avez une colonne d’index, disons id, vous pouvez renvoyer l’identifiant précédent et suivant dans une requête SQL. Remplacez: id avec votre valeur

 SELECT IFNULL((SELECT id FROM table WHERE id < :id ORDER BY id DESC LIMIT 1),0) as previous, IFNULL((SELECT id FROM table WHERE id > :id ORDER BY id ASC LIMIT 1),0) as next 

Ma solution pour obtenir la suite et les aperçus enregistrent également pour revenir au premier enregistrement si je suis par la dernière et vice versa

Je n’utilise pas l’id j’utilise le titre pour les bonnes URL

J’utilise CodeMiter HMVC

 $id = $this->_get_id_from_url($url); //get the next id $next_sql = $this->_custom_query("select * from projects where id = (select min(id) from projects where id > $id)"); foreach ($next_sql->result() as $row) { $next_id = $row->url; } if (!empty($next_id)) { $next_id = $next_id; } else { $first_id = $this->_custom_query("select * from projects where id = (SELECT MIN(id) FROM projects)"); foreach ($first_id->result() as $row) { $next_id = $row->url; } } //get the prev id $prev_sql = $this->_custom_query("select * from projects where id = (select max(id) from projects where id < $id)"); foreach ($prev_sql->result() as $row) { $prev_id = $row->url; } if (!empty($prev_id)) { $prev_id = $prev_id; } else { $last_id = $this->_custom_query("select * from projects where id = (SELECT MAX(id) FROM projects)"); foreach ($last_id->result() as $row) { $prev_id = $row->url; } } 

Optimisation de l’approche @Don pour utiliser une seule requête

 SELECT * from ( SELECT @rownum:=@rownum+1 row, CASE a.id WHEN 'CurrentArticleID' THEN @currentrow:=@rownum ELSE NULL END as 'current_row', a.* FROM articles a, (SELECT @currentrow:=0) c, (SELECT @rownum:=0) r ORDER BY `date`, id DESC ) as article_with_row where row > @currentrow - 2 limit 3 

changez CurrentArticleID avec l’ID d’article actuel comme

 SELECT * from ( SELECT @rownum:=@rownum+1 row, CASE a.id WHEN '100' THEN @currentrow:=@rownum ELSE NULL END as 'current_row', a.* FROM articles a, (SELECT @currentrow:=0) c, (SELECT @rownum:=0) r ORDER BY `date`, id DESC ) as article_with_row where row > @currentrow - 2 limit 3 

Sélectionnez top 1 * from foo where id> 4 order par id asc

Je pense que pour avoir la vraie rangée suivante ou précédente dans la table SQL, nous avons besoin de la valeur réelle avec égale, () renvoyer plus d’une si vous devez changer la position de la ligne dans une table de classement.

nous avons besoin de la valeur $position pour rechercher la ligne des neighbours Dans ma table, j’ai créé une colonne ‘position’

et requête SQL pour obtenir la ligne nécessaire est:

pour suivant:

 SELECT * FROM `my_table` WHERE id = (SELECT (id) FROM my_table WHERE position = ($position+1)) LIMIT 1 

pour les précédents:

  SELECT * FROM my_table WHERE id = (SELECT (id) FROM my_table WHERE `position` = ($position-1)) LIMIT 1