Sort mysqli from a many-to-many table - php

I'm trying to make a internal web based message system, with a *amp system, primarily for learning purposes. I don't know if this is a trivial topic, but I'm having difficulties so please bear with me.
The goal is to list all the contacts ordered by the last message sent / received.
Currently without sorting it the SQL looks like this
$query = "SELECT username, user.id as user_id,
(SELECT COUNT(message_read)
FROM message_user
WHERE message_read = 0
AND sent_id = user_id
AND receive_id = {$userId}) as unread
FROM user
WHERE user.id IN
(SELECT contact_id FROM allowed_contact WHERE user_id = {$userId})
;";
The structure of the tables are:
The user table has an id,
That links to the message_user table which has a sent_id and a receive_id,
The message_user has a message_id that corresponds to the message.id,
The message table has a timestamp.
I would like this to be done in SQL but if it comes down to PHP I resign to resort to that.

This works.
SELECT `u`.`id` AS user_id, username,
(SELECT COUNT(message_user.message_read)
FROM message_user
WHERE message_user.message_read = 0
AND sent_id = user_id
AND receive_id = {$userId}) as unread
FROM `user` AS `u`
LEFT JOIN `message_user` AS `mu`
ON
(CASE WHEN `u`.`id` != {$userId}
THEN `u`.`id` = `mu`.`sent_id`
WHEN `mu`.`sent_id` = {$userId} AND `mu`.`receive_id` = {$userId}
THEN `u`.`id` = `mu`.`sent_id`
END)
OR
(CASE WHEN `u`.`id` != {$userId}
THEN `u`.`id` = `mu`.`receive_id`
END)
LEFT JOIN `message` AS `m` ON `m`.`id` = `mu`.`message_id`
WHERE u.id IN
(SELECT contact_id FROM allowed_contact WHERE user_id = {$userId})
GROUP BY u.id
ORDER BY MAX(`m`.`timestamp`) DESC;
This broke down the problem I was having.
#Andreas thanks for time and help.

Use 2 LEFT JOIN with a DISTINCT (untested):
SELECT DISTINCT `u`.`id`
FROM `user` AS `u`
LEFT JOIN `message_user` AS `mu` ON `u`.`id` = `mu`.`sent_id` OR `u`.`id` = `mu`.`receive_id`
LEFT JOIN `message` AS `m` ON `m`.`id` = `mu`.`message_id`
ORDER BY `m`.`timestamp` DESC;

Related

Specify columns in INNER JOINed table

comment table and post table both has column named user_id
I cannot specify both table's user_id
for using some if else condition later I need both the user_id as a different name (I'm trying to use AS).
I tried different way but query not working:
$sql="SELECT `post_id`, `comment_id`, `comment`, `user_id`, `username`,
`is_marked` `post`.`user_id` AS `p_uid` FROM `comment` INNER JOIN `user` ON
`comment`.`user_id` = `user`.`id` INNER JOIN `post` ON
`user`.`id`=`post`.`user_id` ORDER BY `comment_id` DESC";
$result = mysqli_query($con, $sql);
if ($result) {
while ($row=mysqli_fetch_assoc($result)) {
$post_user_id = $row['p_uid'];
You could alias table name with other name and get column. View example:
SELECT C.comment_id, U.user_id
FROM comment C INNER JOIN user u ON C.user_id = U.id
I would do:
SELECT c.post_id,
c.comment_id,
c.comment,
c.user_id AS c_uid,
c.username,
c.is_marked,
p.user_id AS p_uid
FROM comment c
INNER JOIN user u ON c.user_id = u.id
INNER JOIN post p ON c.user_id = p.id
ORDER BY c.comment_id DESC
Define aliases for the tables, and the selected fields. It makes it simpler to read than putting the table names all the time.
In your PHP you can then reference $row['c_uid'] or $row['p_uid'].

MYsql Query Error Join with Group by not working

Table -1 : Comment id, comment,user_id,comment Date
Table -2: Users id, user_name, full_name, password
now i want to get user detaiils records who is last comment
like
query is :
select c.*,
(select user_name
from users
where id = c.user_id
) as user_name,
(select full_name
from users
where id = c.user_id
) as full_name
from comment as c, users as u
group by c.user_id
order by comment_date DESC
SELECT Users.*,
Comment.*
FROM Users
INNER JOIN Comment ON (Comment.user_id = Users.id)
GROUP BY Users.id
ORDER BY Comment.id DESC
that should work
Here is your query
select users.* from users inner join comments on
users.user_id = comments.user_id
order by comments.comment_date desc limit 1
Another way to do this
select * from users where user_id =
(select user_id from comments order by comment_date desc limit 1)

MySQL SELECT distinct very slow

For my mobile App i am using a web service to get the images and all records from the MySQL database, its like Instagram.
But SELECT DISTINCT taking more than 7 - 8 seconds.is there any thing that i can do for reduce the time?
SELECT distinct count(*) as totalrecord ,p.description,p.photo_id ,p.user_id,p.imagepath1 ,p.friends, p.is_report_photo,
p.imagepath2,p.imagepath3,p.imagepath4,p.imagepath5,p.count_comment,p.count_like,p.created as photo_created ,
(select username from users where id = p.user_id) as username ,
(select country from users where id = p.user_id) as country,
(select email from users where id = p.user_id) as email ,
(select image_path from users where id = p.user_id) as image_path ,
(select gender from users where id = p.user_id) as gender,
(select privacy from users where id = p.user_id) as privacy,
(select audio_privacy from users where id = p.user_id) as audio_privacy,
(select video_privacy from users where id = p.user_id) as video_privacy,
(select photo_privacy from users where id = p.user_id) as photo_privacy,
If(pl.user_id && pl.photo_id !='',like_status,0) as islike ,
If(pr.user_id && pr.photo_id !='',1,0) as isreport,
p.user_visibility
from friends as fr
inner join users as u on u.id = (select distinct if (fr.user_id != $user_id,fr.user_id,(fr.to_user_id)) as rd
from friends) && fr.read_status = '1'
inner join photos as p on (p.user_visibility = 'p')
LEFT JOIN photolike as pl ON pl.photo_id = p.photo_id && pl.user_id = $user_id
LEFT JOIN photo_report as pr on pl. photo_id = pr.photo_id && pr.user_id = $user_id
ORDER BY p.photo_id DESC;
Use mysql indexing that will reduce the time
Try using group-by clause instead of distinct.

MySql : left join users table with transactions table return several rows

I have 2 tables : users and paypal_transactions
For each user, we have an id (named user_id in paypal_transactions table)
A user may have several paypal_transactions. Relation one to many
I need to grab the latest transaction id (ordered by date_dt DESC) when I do my query
My current query :
SELECT `Transaction`.*, `User`.*, `Tipster`.`username`
FROM `pronostics_framework`.`users` AS `User`
LEFT JOIN `pronostics_framework`.`users` AS `Tipster` ON (`User`.`tipster_id` = `Tipster`.`id`)
LEFT JOIN `pronostics_framework`.`paypal_transactions` AS `Transaction` ON (`User`.`id` = `Transaction`.`user_id`)
ORDER BY `User`.`id` DESC
LIMIT 500
Currently with one transaction per user, it works fine. BTW with many transactions I still get the 1st entry from paypal_transactions table (the oldest, but I want the latest from now).
I did many tries, without success.
Thanks for your help !
Here you go:
SELECT `Transaction`.*, `User`.*, `Tipster`.`username`
FROM `pronostics_framework`.`users` AS `User`
LEFT JOIN `pronostics_framework`.`users` AS `Tipster` ON (`User`.`tipster_id` = `Tipster`.`id`)
LEFT JOIN (SELECT user_id, MAX(date_dt) AS max_date
FROM `pronostics_framework`.paypal_transactions
GROUP BY user_id) AS max_trans
ON User.id = max_trans.user_id
LEFT JOIN `pronostics_framework`.`paypal_transactions` AS `Transaction`
ON (max_trans.user_id = `Transaction`.`user_id` AND max_trans.max_date = Transation.date_dt)
ORDER BY `User`.`id` DESC
LIMIT 500
Another way, based on the first query in the first answer at Retrieving the last record in each group:
SELECT `Transaction`.*, `User`.*, `Tipster`.`username`
FROM `pronostics_framework`.`users` AS `User`
LEFT JOIN `pronostics_framework`.`users` AS `Tipster` ON (`User`.`tipster_id` = `Tipster`.`id`)
LEFT JOIN `pronostics_framework`.`paypal_transactions` AS `Transaction` ON Transaction.user_id = User.id
LEFT JOIN `pronostics_framework`.paypal_transactions AS Transactions1
ON Transactions1.user_id = Transactions.user_id AND Transactions1.user_id > Transactions.user_id
WHERE Transactions1.user_id IS NULL
ORDER BY `User`.`id` DESC
LIMIT 500

Select approved comments and unapproved comments of current user MySQL PHP

I'm new to mysql and I have a problem with selecting data from mysql database:
$post_id = 3;
$current_user_id = 1;
$query = "SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND `comments`.`status` = 1
AND `users`.`status` = 1
ORDER BY `comments`.`date` desc";
This select, selects all approved comments from database, but also, in this select, I need all unapproved comments of $current_user_id,
Result must look like:
[all approved post comments] + [all unapproved post comments of $current_user_id]
not sure if this will really work, but just give a try and see. I can't test the query since we don't have the schema.
SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND (
(`comments`.`status` = 1 AND `users`.`status` = 1)
OR
( `comments`.`status` = 0 AND `users`.`id`= '$current_user_id' )
)
ORDER BY `comments`.`date` desc
What I thought is select all the approved comments OR ( comments that are not approved, but from this user ). You might have to alter the query till you get what you really needed, I'm just giving you the idea, not the exact query. Hope this will help you.
SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND `comments`.`status` = 1
AND `users`.`status` = 1
UNION ALL
SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND `comments`.`status` = 0
AND `users`.`id` = '$current_user_id'
ORDER BY `comments`.`date` desc

Categories