MySQL next and prev record issue - php

I made this php script and i am tryin to make it to return next and previus row, but there is one problem when i input my id the script return different thing for example :
This is my DB
ID String
1 Test 1
2 Test 2
3 Test 3
4 Test 4
So if i put ./index.php?id=1 this returns the result of id=2 and id=2 => id=3 and so on...
My question is how to fix it to return accurate result not +1. I tried with <= or => operators the result is correct, but then my links doesnt work.
Here is the script
<?php
if(isset($_GET['id']))
{
$id = (int)$_GET['id'];
}else
{
$id = 0;
}
$stmt1 = $db->prepare("SELECT * FROM records WHERE id > ? ORDER BY id ASC LIMIT 1");
$stmt1->bindValue(1,$id);
$stmt1->execute();
$row = $stmt1->fetch();
$stmt2 = $db->prepare("SELECT * FROM records WHERE id < ? ORDER BY id DESC LIMIT 1");
$stmt2->bindValue(1,$id);
$stmt2->execute();
$row = $stmt2->fetch();
echo $row['id'];
echo "<br/>";
echo $row['string'];
?>

I am not sure if the problem as silly as that, but I have no other explanation.
To have your page you need to make 3 selects:
to get current page data
to get prev id
to get next one
But I can see only 2 selects
So, you have to select data for the very page to show
if(isset($_GET['id']))
{
$sql = "SELECT * FROM records WHERE id = ?";
$stm = $db->prepare($sql);
$stm->execute(array($_GET['id']));
} else {
$sql = "SELECT * FROM records ORDER BY id ASC LIMIT 1";
$stm = $db->query($sql);
}
$row = $stm->fetch();
and now you can go for getting prev and next ids
$sql = "SELECT id FROM records WHERE id < ? LIMIT 1";
$stm = $db->prepare($sql);
$stm->execute(array($row['id']));
$prev = $stm->fetchColumn();
$sql = "SELECT id FROM records WHERE id > ? LIMIT 1";
$stm = $db->prepare($sql);
$stm->execute(array($row['id']));
$next = $stm->fetchColumn();

i am tryin to make it to return next and previus row
There is no such thing as "previous" or "next" row in a table. Without explicit ordering, tables must be considered as unordered set of rows. And you shouldn't rely on auto_increment field to be sequentially numbered. For example:
because there was interleaved insert on the table,
because the server is allowed to reuse auto_increment after row deletion.
You probably have to modify your table structure to add a sequence number:
CREATE TABLE tbl (id in primary key not null auto_increment,
sequence_number int unique,
value char(40));
While inserting your data you might rely on something like that:
INSERT INTO tbl (sequence_number, value)
VALUES (SELECT COUNT(*) FROM tbl, ?)
And the query for the "next" and "prev":
SELECT * FROM tbl WHERE sequence_number = ?-1 OR sequence_number = ?+1
ORDER BY sequence_number;

Related

Get the id before the current one

I have the following code to have as a result the id previous to the current one, I do not use any calculation such as adding one or subtracting one because sometimes I have skipped ids, for example, from 1 to 3 and from 3 to 4, can you think of any solution? Thanks for your time
$sql3 = "SELECT * FROM videos WHERE temporada=$idTemporada AND id<$id";
$res3 = mysqli_query($conn, $sql3);
$ant_cap = mysqli_fetch_assoc($res3);
echo $ant_cap['id'];
if my current id is 5 and the previous database id is 3 then the result of the echo of $ant_cap['id'] is 3
$sql3 = "SELECT * FROM videos WHERE temporada=$idTemporada AND id<$id";
$res3 = mysqli_query($conn, $sql3);
$ant_cap = mysqli_fetch_assoc($res3);
echo $ant_cap['id'];
Use MAX(id) to get the highest ID below the current one.
$stmt = $conn->prepare("
SELECT MAX(id) as previous_id
FROM videos
WHERE temporada = ? AND id < ?");
$stmt->bind_param("ii", $idTemporada, $id);
$stmt->execute();
$res3 = $stmt->get_result();
$ant_cap = mysqli_fetch_assoc($res3);
echo $ant_cap['previous_id'];

How select random column value from Mysql database using PHP

I'm trying to fetch random column from database using Rand() function.
It's returning random value but many time it is returning duplicate.
This is what my database table look like.
Column
Type
Null
Default
no
int(30)
No
postid
varchar(100)
Yes
NULL
byuser
varchar(32)
Yes
NULL
likeslimit
int(30)
No
createdon
date
No
And this is what my PHP code is.
$query = mysqli_query(
$mysql,
"SELECT postid FROM history ORDER BY Rand() LIMIT 1"
);
if (mysqli_num_rows($query) == 1) {
while ($row = mysqli_fetch_assoc($query)) {
echo $row['postid'];
}
}
I want it to always return random never the same till the end of data reached.
Don't use loop and condition you want only 1 limit try this
$query = mysqli_query(
$mysql,
"SELECT postid FROM history ORDER BY Rand() LIMIT 1"
);
$row = mysqli_fetch_assoc($query)
echo $row['postid'];
This is the way RAND in mysql works and will repeat the results from time to time. But you can achieve such functionality by using mysql with php.
$query = mysqli_query($mysql, "SELECT postid FROM cacheTable WHERE 1 ORDER BY RAND() LIMIT 1");
$row = mysqli_fetch_assoc($query);
$foundId = (int)$row['postid'];
if((int) $foundId === 0) { // NO records left in cacheTable then fill it up again
mysqli_query($mysql, "INSERT INTO cacheTable (postid) SELECT postid FROM history");
$query = mysqli_query($mysql, "SELECT postid FROM cacheTable WHERE 1 ORDER BY RAND() LIMIT 1");
$row = mysqli_fetch_assoc($query);
$foundId = (int) $row['postid'];
}
mysqli_query($mysql, "DELETE FROM cacheTable WHERE postid=".$foundId); // DELETE the record
$query = mysqli_query($mysql, "SELECT * FROM history WHERE postid=".$foundId);
$result = mysqli_fetch_assoc($query);
cacheTable will have only one column - ID (primary key) which will hold the corresponding ID (primary key) from history. cacheTable structure:
|------
|Column|Type|Null|Default
|------
|postid|varchar(100)|Yes|NULL
|-----
cacheTable will fill with all the ids from history table (it will be done once the cacheTable is empty). You will select rand result from the cacheTable and you will delete it then so it will not appear in the next selects. When we are out of records in cache table it will populate again.
NB: this approach has one major drawback - when you have new entries in history table they won't be available in cache table until it is empty and filled again.
This is the code Samir Nabil Suggested :
session_start();
$_SESSION['dupes'] = array();
$query = mysqli_query(
$mysql,
"SELECT postid FROM history ORDER BY Rand() LIMIT 1"
);
if (mysqli_num_rows($query) == 1) {
while ($row = mysqli_fetch_assoc($query)) {
if (!in_array($row['postid'], $_SESSION['dupes'])) {
echo $row['postid'];
$_SESSION['dupes'][] = $row['postid'];
}
}
}

getting all mysql results that is less than given id

i am working on a timeline for my website but i am having some problem when i ran the query to select all id that is less than given identifier its still return the identifier result upon every query
example if identifier is id=4 i want to select everything less than 4 and not from 4 > 3 > 2 > 1 i want it to be 3 > 2 > 1
here is my php. i know its not secure or what not but i have written it in prepared statement and get the same thign so i need some here.
if(isSet($_POST['lastmsg']))
{
$feed_id = mysqli_real_escape_string($con, $_POST['lastmsg']);
$get1 = mysqli_query($con, 'SELECT receiver FROM connection where sender="'.$_SESSION['userid'].'"');
$id_feed = array();
while($id_result1 = mysqli_fetch_array($get1)){
$id_feed[] = $id_result1['receiver'];
$ids1 = join(',', $id_feed);
$get_feed1 = mysqli_query ($con, "select * from feed where users in '".$ids1."' or users='".$_SESSION['userid']."' and 'feed_id' < '".$feed_id."' ORDER BY feed_id DESC LIMIT 2");
}
while($res1 = mysqli_fetch_array($get_feed1)){
echo $load = $res1['feed_id'];
}
}

Getting record from another table with id recognition

there are tables artist, track, & etc
in the artist table there is :
id
name
cover
desc
and in the track table there is :
id
name
desc
artistid
so if i goto track.php?id=1 and then they print
id
name
desc
artistid i want to make this show the record from artist table with id recognition
and can you show me how to make multiple filter from recordset. because i have field "pubid" when the value is 1 this mean publish and then if the value is 2 this mean unpublish
sorry bad english
thx u so much
Have a look at SQL Join. In order to only get records which may be published, you'll have to add another WHERE clause. Like:
SELECT name, desc FROM track WHERE id = $id AND pubid = 1;
track.php?id=1
or
track.php?id=1&pubid=1
track.php?id=1&pubid=2
<?php
if (isset($_GET['id'])) {
$artistid = $_GET['id'];
if (isset($_GET['pubid'])) {
$pudid = $_GET['pubid'];
$sql = "select `id`, `name` from `track` where `artistid` = {$artistid} and `pubid` = {$pupid} order by `desc`";
} else
$sql = "select `id`, `name` from `track` where `artistid` = {$artistid} order by `desc`";
$query = mysql_query($sql);
while (($row = mysql_fetch_array($query)) !== false) {
echo $row['name'];
}
}

How can I optimise this mysql/php query?

My page displays an image, and I want to display the previous and next image that is relevant to the current one. At the moment I run the same query 3x and modify the "where" statement with =, >, <.
It works but I feel there must be a better way to do this.
The image id's are not 1,2,3,4,5. and could be 1,2,10,20,21 etc. But if it is much more efficient I am willing to change this.
mysql_select_db("database", $conPro);
$currentid = mysql_real_escape_string($_GET['currentid']);
$query ="SELECT * FROM database WHERE id ='".$currentid."' LIMIT 1 ";
$result = mysql_query($query,$conPro) or die(mysql_error());
$affected_rows = mysql_num_rows($result);
if ($affected_rows==1)
{
$row = mysql_fetch_array($result)or die ('error:' . mysql_error());
$current_id = $row['id'];
$current_header = $row['title'];
$current_description =$row['desc'];
$current_image = "http://".$row['img'];
$current_url = "http://".$row['id']."/".$db_title."/";
$current_thumb = "http://".$row['cloud'];
}
mysql_select_db("database", $conPro);
$query ="SELECT * FROM database WHERE id <'".$currentid."' ORDER BY id DESC LIMIT 1 ";
$result = mysql_query($query,$conPro) or die(mysql_error());
$affected_rows = mysql_num_rows($result);
if ($affected_rows==1)
{
$row = mysql_fetch_array($result)or die ('error:' . mysql_error());
$previous_id = $row['id'];
$previous_header = $row['title'];
$previous_description =$row['desc'];
$previous_image = "http://".$row['img'];
$previous_url = "http://".$row['id']."/".$db_title."/";
$previous_thumb = "http://".$row['cloud'];
}else{
$previous_none = "true"; //no rows found
}
mysql_select_db("database", $conPro);
$query ="SELECT * FROM database WHERE id >'".$currentid."' ORDER BY id ASC LIMIT 1 ";
$result = mysql_query($query,$conPro) or die(mysql_error());
$affected_rows = mysql_num_rows($result);
if ($affected_rows==1)
{
$row = mysql_fetch_array($result)or die ('error:' . mysql_error());
$next_id = $row['id'];
$next_header = $row['title'];
$next_description =$row['desc'];
$next_image = "http://".$row['img'];
$next_url = "http://".$row['id']."/".$db_title."/";
$next_thumb = "http://".$row['cloud'];
}else{
$next_none = "true"; //no rows found
}
mysql_close($conPro);
Thank you for your time
You don't have to do select_db each time. Once you 'select' a db, it stays selected until you select something else.
You can't really get away from doing two separate queries to get the next/previous images, but you can fake it by using a union query:
(SELECT 'next' AS position, ...
FROM yourtable
WHERE (id > $currentid)
ORDER BY id ASC
LIMIT 1)
UNION
(SELECT 'prev' AS position, ...
FROM yourtable
WHERE (id < $currentid)
ORDER BY id DESC
LIMIT 1)
This would return two rows, containing a pseudofield named 'position' which will allow you to easily identify which row is the 'next' record, and which is the 'previous' one. Note that the brackets are required so that the 'order by' clauses apply to the individual queries. Without, mysql will take the order by clause from the last query in the union sequence and apply it to the full union results.
You can get the "previous" one first WHERE id <'".$currentid."' ORDER BY id DESC, and then query for two "above" it: SELECT * FROM database WHERE id >= '".$currentid."' ORDER BY id ASC then it takes only two queries instead of three.

Categories