Sorting the SQL data Using DISTINCT - php

I was trying to build a chat plugin in my site but I got problem while sorting the incoming messages in the Inbox. When I use the code below, it doesn't order the messages according to new sent but orders according to history of sent messages:
E.g. if I send message to "A" at first, "B" after that and "C" at last, the code I works fine up to here. It shows C at Top, B at middle and A at end. But When I again send message to B, the "B" doesn't come up at the top.
Edit:
Someone tagged this question as duplicate. The problem about that question is abit different. I already did extract the unique row (as asked by that question) but I cannot sort it according to time.
Here is the code I use and please ignore the mysql_* tag I used here. It is just for testing.
<?php
$sql = mysql_query("SELECT DISTINCT `from` FROM `message` WHERE `to`='$username' ORDER BY `time` DESC");
// using loop
while($row = mysql_fetch_assoc($sql)){
echo $row['from'];
echo "<br/>";
}
?>

You are ordering by a not selected column
if you want order by time i think you should select this column :
try
$sql = mysql_query("SELECT `from` , max(`time`) FROM `message`
WHERE `to`='$username' GROUP BY `from` ORDER BY `time` DESC " );
Grouping by not require distinct

For messages you can select rows ordered by id desc like this:
SELECT * FROM `message` WHERE `to`='username' ORDER BY id DESC
Sender list you can get like this:
SELECT MAX(`id`),`from` FROM `message` WHERE `to`='username' GROUP BY `from` ORDER BY MAX(`id`) DESC

Do not order messages by time.
The best practice is to having unique autoincrement id column in message table and ordering messages by they's ids

Related

SQL order by datetime

I have 3 tables:
chatmsgs with the columns
itemid, sender, receiver, message, datetime, status
users with the columns
userid, username, phone, email, avatar, online, password
items with the columns
itemid, category, make, type, mainimage, title, price
I am trying to create a list of chats between the current user and some other user on a specific item and order the list by the chat with the most recent message (based on timestamp).
My current query is this:
<?php
$currentuser=$_SESSION['userid'];
$sqls="SELECT DISTINCT itemid,sender,receiver FROM chatmsgs ORDER BY datetime DESC";
$results=mysqli_query($db,$sqls);
while($rows=mysqli_fetch_assoc($results)){
$itemid=$rows['itemid']; $sender=$rows['sender']; $receiver=$rows['receiver']; #$message=$rows['message'];
$sqll="SELECT * FROM items WHERE itemid = '".$itemid."'";
$resultt=mysqli_query($db,$sqll);
while($roww=mysqli_fetch_assoc($resultt)){
$itemid=$roww['itemid']; $title=$roww['title']; $status=$roww['status']; $userid=$roww['userid'];
#$sqlx = "SELECT * FROM users WHERE userid = '".$userid."' AND userid != '".$currentuser."'";
$sqlx = "SELECT * FROM users WHERE userid = '".$userid."'";
$resultx=mysqli_query($db,$sqlx);
while($rowx=mysqli_fetch_assoc($resultx)){
$avatar=$rowx['avatar']; $username=$rowx['username']; $user=$rowx['userid'];
$sq="SELECT * FROM chatmsgs WHERE itemid = '".$itemid."' AND ((sender = '".$sender."' AND receiver = '".$receiver."') OR (sender = '".$receiver."' AND receiver = '".$sender."')) ORDER BY id ASC";
$resul=mysqli_query($db,$sq);
while($ro=mysqli_fetch_assoc($resul)){
$message=$ro['message'];
$ldate=date_format(date_create($ro['datetime']),"M d");
}
echo '
<li>
My list item
</li>
';
}
}
}
?>
I have so far been able to list the chats but I'm unable to sort it.
I know this is not the best way to do this but it's the only way I know how. Would appreciate better ways.
I would start by getting all chat messages associated with just the given user in question. By doing a UNION as both the sender and receiver, if you have an index on each column respectively, the query should be very fast. From that, you can now query the rest of the data all in one quick run something like below.
You can order the data by whatever... From your while loops, it looked like you were doing all things for a given Item ID before moving to the next, so I have the order by clause by the item ID. Now, from within each item, I have ordered by the date/time in descending order with newest chat message first, but you could change that.
Another possible change is you may want the items displayed based on which is the MOST RECENT item that has chat activity first. For example, if a chat from someone was from a year ago, vs one that was just this week, you might want the current first. I would alter the query slightly.
select
um.itemid,
cm.message,
cm.datetime,
cm.status,
uFrom.username senderName,
uFrom.avatar senderAvatar,
uTo.userName receiptName,
uTo.avatar receiptAvatar,
i.category,
i.make,
i.type,
i.mainImage,
i.title,
i.price
from
( select distinct itemid
from chatMsgs
where sender = $currentuser
UNION
select distinct itemid
from chatMsgs
where receiver = $currentuser ) UM
JOIN ChatMsgs ch
on UM.ItemID = ch.ItemID
JOIN Users uFrom
on ch.sender = uFrom.userid
JOIN Users uTo
on ch.receiver = uTo.userid
JOIN Items i
on ch.itemID = i.itemid
order by
um.itemid,
cm.datetime desc
The format is not in php format, but you can see the only place you need a parameter is where the user ID is. All the details come along in the results including the respective avatars, titles, messages, from user and recipient user too. Take what you need in one query.
I would expect two individual indexes on your chatmsgs table. One on the sender, one on the receiver.

Fetching data with Group by, How to select the latest or greatest id? (PHP to MySQL)

I wanted to fetch data from MySQL with PHP when a user inputs something. I have this code.
$query = "SELECT * FROM mealplans WHERE plantitle LIKE '%$inputText%' AND `STATUS` = 1 OR plantitle LIKE '%$inputText%' AND userid = '$userid' GROUP BY plantitle, userid";
$result = mysqli_query($con, $query);
It works fine however, it fetches the oldest or first data from the group. How do I select the newest data?
I've search and found possible solutions by using FROM, JOIN, IN, etc. However, I do not know how to use them since I only know the basics. Hopefully someone could explain one solution for me.
There is a simple solution that you can do.
You can order your data to DESC order. I'm sure that you have an id(primary key) in your table.You just have to order all your datas' to DESC order of ids .So that your last inserted data set will be the one to be fetched since it's on the top.
change your query to: (add your primary key(in the following query i have added it as id) in the ORDER BY syntax)
$query = "SELECT * FROM mealplans WHERE plantitle LIKE '%$inputText%' AND `STATUS` = 1 OR plantitle LIKE '%$inputText%' AND userid = '$userid' GROUP BY plantitle, userid ORDER BY `ID` DESC"
Just add a condition in your query which only retrieves the row having the greatest id.
Find out the id first and then you can use the same query for that id:
SELECT MAX(id) FROM mealplans WHERE plantitle LIKE '%$inputText%' AND `STATUS` = 1 OR plantitle LIKE '%$inputText%' AND userid = '$userid' GROUP BY plantitle, userid
After getting the id and storing it in a variable (say $temp):
SELECT * from mealplans where `id` = $temp

Retrieve table ID from selected row

So I've been stuck on this for a while and I can't find anything on google for this specific thing.
I have this small snippet of code
$link = mysqli_connect("localhost", 'username','password',"database");
$sql = "SELECT * FROM `uploads` ORDER BY id DESC LIMIT 0, 1";
Which should select the latest table by order of id's right?
Well what I want to do is return this id. So if I have 5 items/rows I want to grab the latest (5 in this case) id of the table, and return it. With the eventual goal of using this returned id in javascript but that's a worry for later, right now I just want it in plaintext where the result should only be the id.
This is probably a duplicate question but I can't for the life of me find what I should google to get there
EDIT:
I guess I should clarify further. I know I'm able to do
$sql = "SELECT ID FROM `uploads` ORDER BY id DESC LIMIT 0, 1";
but whenever I try to actually retrieve it/print it its returned as a string instead of the ID.
EDIT 2: I, thanks to some comments, have managed to figure it out. Sorry for the badly worded everything, I'm new to this and as I said don't know how to word it.
SOLUTION:
After just throwing away the $sql thing I added:
$result = mysqli_query($link,"SELECT * FROM `uploads`");
Then I simply did
echo mysqli_num_rows($result);
To echo out the number of rows/what I called the "ID".
Sorry for all the confusion, thanks to those that tried to help. To the others there's no need to be rude.
If I understood your question correctly, you want to get the ID field only, so you have two options:
Option 1 (Recommended)
Given your code
$sql = "SELECT * FROM `uploads` ORDER BY id DESC LIMIT 0, 1";
Change it to:
$sql = "SELECT ID FROM `uploads` ORDER BY id DESC LIMIT 0, 1";
This way, your getting just that ID field you're after. Nothing else is returned from each row.
Option 2
Keep your sql query as it is, and get the ID field from each row in your results (it's an array, so you can retrieve only one field by using its index or name).
Of course, I assume there's an ID field in your table!
Just select the ID.
SELECT id
FROM uploads
ORDER BY id DESC
LIMIT 1;
Simply select what you want.
$sql = "SELECT id FROM `uploads` ORDER BY id DESC LIMIT 0, 1";
The * means you want to select every column there is. However, SQL gives you the possibility to select the specific columns you want. You could also do something like
$sql = "SELECT id, name, title, somethingelse FROM `uploads` ORDER BY id DESC LIMIT 0, 1";
and you'd receive these 4 fields as an array.

Reverse while loop

while($data=$SQL->fetch(PDO::FETCH_ASSOC)){
echo $data=['message'];
}
is that possible to reverse while loop?
I have a page echo out messages and I need put in reverse
SQL- DESC LIMIT 20
fetch last 20 messages
but my chat box is print in reverse
message 1 (oldest message)
message 2
message 3 (newest message)
You should define the order of the data set in your original SQL query.
See documentation for the ORDER BY clause.
Update
It seems that the OP wants the 20 newest messages, but ordered in reverse. Then you need to perform a subquery like this:
SELECT `message`
FROM (SELECT * FROM `table`
ORDER BY `id` DESC
LIMIT 20) AS `i`
ORDER BY `i`.`id` ASC;
After fetching records You can just reverse your returned array
http://us1.php.net/array_reverse
If you really want to reverse the data in PHP, you can use array_reverse:
// Fetch all records
$data = $SQL->fetchAll(PDO::FETCH_ASSOC);
// Reverse them
$data = array_reverse($data);
foreach ($data as $record) {
echo $record['message'];
}
Although I would recommend ordering in SQL, as it will be faster.

Can`t MAX() function be used with mysqli?

I can not find a proper answer to this question. I have a very simple code for making a query in mysql to select the row with the maximum value in a determined column (called popularity) from a table (called comments). Every row has a column named comment_id
here is the code:
$connect_error = 'Sorry, try again, there was a connection error';
$con = mysqli_connect('localhost','user_name','password') or die($connect_error);
mysqli_select_db($con, 'database') or die($connect_error);
$result = mysqli_query($con, "SELECT MAX(`popularity`) FROM `comments`");
while ($row = mysqli_fetch_assoc($result)) {
$most_popular = $row['comment_id'];
}
echo "most popular is: $most_popular";
mysqli_free_result($result);
mysqli_close($con);
the screen does not show a proper result. Can someone give me an advice in this regard?
Thank you
You are looking to display the comment_id field, but you don't have that in your SELECT query. You are only selecting the max popularity value, and nothing else.
Try this for your query:
SELECT comment_id FROM comments ORDER BY popularity DESC LIMIT 1
This is sorting your comments by popularity, and then just picking the top one.
Of course you can easily change that to select more columns or even a SELECT * if you want to be able to display other values in this record.
To select the row with max 'popularity' column use this query;
$result = mysqli_query($con, "SELECT * FROM `comments` ORDER BY `popularity` DESC LIMIT 1");
In case you want all sorted by popularity remove the LIMIT 1...
You need
SELECT MAX(`popularity`) AS comment_id FROM `comments`
This will give the column the correct name for the associated array.
You are trying to read the result from a column named comment_id when the result from your query will be named MAX(popularity)
Run this query in mysql "SELECT MAX(popularity) FROM comments" first.The output of this gives you the index to use with $row[index] ie first row which in this case the index will be popularity else just change $row[content_id] to $row[popularity]

Categories