I am currently developing a social media app which includes users (you can add them as friend) and posts (text, image etc...)
I want to show to user 5 newest posts compared to user's posts and user's friends' posts when user enters to the app.
I know this is not the wisest method to achieve this but so far i did this. Query returned only one post while there are more and its not even newest nor oldest. I think the problem is in "OR" clause.
I get all sno's of friends of user and put in WHERE clause one by one with "OR" clause.
//CURRENT FRIENDS
$sql = 'SELECT current AS currents FROM friends WHERE sno = :sno';
$query = $this -> conn -> prepare($sql);
$query -> execute(array(':sno' => $usersSno));
$friends = $query -> fetchObject() -> currents;
//SELECT 5 NEWEST POST
$sql = 'SELECT operationId FROM posts WHERE operationId = :operationId';
$array = array(':operationId' => $usersSno);
if(isset($friends)) {
$ids = explode(",", $friends);
for($i = 0; $i < count($ids); $i++) {
$sql = $sql.' OR operationId = :operationId'.$i;
$array[':operationId'.$i] = $ids[$i];
}
}
if($from == null)
$sql = $sql.' ORDER BY operationId DESC LIMIT 5';
else {
$sql = $sql.' AND operationId < :from ORDER BY operationId DESC LIMIT 5';
$array[':from'] = $from;
}
$query = $this -> conn -> prepare($sql);
$query -> execute($array);
$result = $query -> fetchAll(PDO::FETCH_ASSOC);
User's sno is 1 and user has two friends which their sno's are 2 and 75.
echo $sql;
SELECT operationId FROM posts WHERE operationId = :operationId OR operationId = :operationId0 OR operationId = :operationId1 ORDER BY operationId DESC LIMIT 5
print_r($array);
Array
(
[:operationId] => 1
[:operationId0] => 2
[:operationId1] => 75
)
I feel like a stupid for realizing my mistake right after starting a bounty for it. I should've use WHERE sno (since i've been getting posts from user's id [sno]) not WHERE operationId in $sql
So echo $sql; be like:
SELECT operationId FROM posts WHERE sno = :sno OR sno = :sno0 OR sno = :sno1 ORDER BY operationId DESC LIMIT 5
And print_r($array) is:
Array
(
[:sno] => 1
[:sno0] => 2
[:sno1] => 75
)
At least i am happy to resolve this problem and even resolving it my own :)
EDIT: I noticed two logical error too in my sql query.
1- Comparing date string with operationId of post
I am comparing posts with their dates (you can also compare with operationId of post) to see which one is newest. But in the code i compared operationId with $from variable (which is a date string).
So final code;
$sql = $sql.') AND createdAt < :from ORDER BY operationId DESC LIMIT 5';
2- OR clauses should be separeted with AND clause by parentheses.
start of parenthese
$sql = 'SELECT operationId FROM posts WHERE (sno= :sno';
end of parenthese
if($from == null)
$sql = $sql.') ORDER BY operationId DESC LIMIT 5';
else {
$sql = $sql.') AND createdAt < :from ORDER BY operationId DESC LIMIT 5';
$array[':from'] = $from;
}
Related
I have a problem with MySQL query and condition. The main problem is user with another ID can see / edit the same leads even though his id != owner.
I tried to change the vars and add '' or "", but none of these help.
$myuser_query = mysqli_query($conn,"SELECT * FROM users WHERE id = '".$_SESSION["id"]."'");
$myuser = mysqli_fetch_assoc($myuser_query);
$myleads = "SELECT * FROM leads WHERE owner = '".$myuser["id"]."' AND status = 1 OR status = 2 ORDER BY RAND() LIMIT 1";
$newleads = $conn->query($myleads);
if ($newleads->num_rows >= 1) {
(Here it's all the client side that's showing the date.)
You need to add parenthesis around the OR conditions in your query. Change this:
$myleads = "SELECT * FROM leads
WHERE owner = '".$myuser["id"]."' AND status = 1 OR status = 2
ORDER BY RAND() LIMIT 1";
To:
$myleads = "SELECT * FROM leads
WHERE owner = '".$myuser["id"]."' AND (status = 1 OR status = 2)
ORDER BY RAND() LIMIT 1";
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'];
}
}
I have a database (GAMES) with userid, name, sports and points.
user1, football, 10 points -
user1, Basketball, 5 points
user2, footbal, 8 points -
user2, Baketball, 3 points
To get the rank of each user by each sports, I am using the following code which is working perfect:
$sql = "SELECT
sports,
FIND_IN_SET(footbal, (
SELECT GROUP_CONCAT(sports
ORDER BY points DESC)
FROM ".GAMES."
)
) AS rank
FROM ".GAMES."
WHERE userid = 1
";
Results:
user1 (1) (1 is the rank)
When I use user2 in WHERE I get: user2 (2)
Now I want a list like this (For more than 1000 users):
1- User1 (1)
2- User2 (2)
3- User15 (44)
3- ....
Any help will be appreciated. I you need more explanation, just ask.
I would do something like this:
$sqls = array();
foreach ($sports as $sport) {
$sqls[] = "SELECT name FROM ".GAME." WHERE sports='".$sport."' ORDER BY points ASC"
}
Then loop through slqs variable to get all the lists.
And finally, to get the parenthesis part, I would do when I will print the list.
You could have 1 select like this:
$sql = 'SELECT * from table_GAMES WHERE points >= 1000 ORDER BY name'
The result would have all users with more than or equal to 1000 sorted alphabetically. You can then display it like this:
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
echo $row['name'];
echo ' (' . $row['points'] . ')';
}
MySQL does not really implement ranking in a convenient way. This is discussed, for example, here: ROW_NUMBER() in MySQL
In that thread linked above you can see some solutions you could try, or alternatively you could use some simpler SQL to get an ordered list and use PHP to calculate/count the ranks:
// ...
$sql = 'SELECT userid, sports, SUM(points) AS total_points FROM games GROUP BY userid, sports ORDER BY sports, SUM(points) DESC';
$result = $mysqli->query($sql);
$rank = null;
$last_sport = null;
$sports_ranking = array();
while($row = $result->fetch_object()) {
if($row->sports == $last_sport) {
$rank++;
} else {
$rank = 1;
}
$sports_ranking[$row->sports][] = array(
'userid' => $row->userid,
'rank' => $rank,
'total_points' => $row->total_points
);
}
echo('<pre>'); print_r($sports_ranking); echo('</pre>');
// ...
Wouldn't this work?
"SELECT * FROM GAMES WHERE userid = ".$userid." ORDER BY points DESC"
I don't see why you would need to use anything else, as you are just ordering by their points.
or if you also want to specify a sport,
"SELECT * FROM GAMES WHERE userid = ".$userid." AND sports = '".$sport"' ORDER BY points DESC"
You would need to use an array to loop through each sport then just use the above query again.
e.g.
$ranks = mysql_query("SELECT * FROM GAMES WHERE userid = ".$userid." AND sports = '".$sport"' ORDER BY points DESC", $database);
$count = 1;
while(list($userid, $name, $sport, $points) = mysql_fetch_row($ranks)) {
//formatting here. table row, paragraph etc or:
echo "$count - $name ($userid)";
$count++;
}
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;
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.