Phpmyadmin not selecting correct vaues - mysql

I am running this query in my database:
SELECT * FROM posts INNER JOIN profile ON posts.user_id = profile.user_id
WHERE posts.user_id IN
(SELECT user_id FROM users WHERE class_name IN
(SELECT class_name FROM classroom WHERE created_by = '456'))
OR posts.user_id IN
(SELECT user_id FROM users WHERE role = 'teacher' AND school_name = 'SK Taman Megah')
ORDER BY posts.created_at DESC;
This is my classroom table:
This is my users table:
This is my post table:
This is my profile table:
This is my output:
Expected output should have a total of 4 rows with post_id of (60,57,61,56) but only 2 was shown. Is there a mistake in the SQL query?

I think following one is what you are expecting:
SELECT * FROM posts INNER JOIN profile ON posts.user_id = profile.user_id where posts.user_id IN (select distinct user_id from users left join classroom on classroom.class_name = users.class_name where classroom.created_by='456' or (users.role='teacher' and users.school_name='SK Taman Megah') )

Related

MySQL - UPDATE query based on SELECT from multiple tables

Help me pls.
I have 3 tables:
users
id rating
posts
id_post rating id_author
photos
id_photo rating id_user
Need query for update users rating based on formula: avg(users posts ratings) + avg(user photos ratings).
Tryed this but works only if user have and posts and photos. If user have photos, and no posts then ratings become 0:
UPDATE users U
inner JOIN
(select id_user, avg(rating) as avgrating
from photos P
group by id_user
) P
on U.id = P.id_user
inner JOIN
(select author_id, avg(rating) as avgrating_posts
from posts PS
group by author_id
) PS
on U.id = PS.author_id
SET
U.rating = (
P.avgrating +
PS.avgrating_posts
)
UPDATE users SET
rating = (
( SELECT AVG(rating) FROM photos
WHERE photos.id_user = users.id AND deleted = 0 AND hidden = 0 AND date_published > 0 ) +
( SELECT AVG(rating) FROM posts
WHERE posts.author_id = users.id AND published_at > 0
) )
Use left join for your inner queries, so if there are no associated records found for a user a null value will be returned.
UPDATE users U
LEFT JOIN (SELECT author_id,
AVG(rating) AS avgrating_posts
FROM posts PS
GROUP BY author_id) PS
ON U.id = PS.author_id
LEFT JOIN (SELECT id_user,
AVG(rating) AS avgrating
FROM photos P
GROUP BY id_user) P
ON U.id = P.id_user
SET U.rating = COALESCE(P.avgrating,0) + COALESCE(PS.avgrating_posts,0)

How to get data from 3 tables with same user id?

I have 3 tables like so
Table 1: UserInfo
user_id userName
123 userOne
Table 2: Post
user_id postContent
123 This is test message
Table 3: LikePost
user_id likesPostId
123 This is test message
I would like to run a query to get total number of post likes, posts, and user information from those 3 tables.
I can do this for each one such as in Post table:
SELECT COUNT(*) FROM Post WHERE Post.user_id = '123'
and SELECT * FROM UserInfo WHERE UserInfo.user_id = '123'
Is anyone have better solution in just 1 query? Thank you so much!
Use a structured query (with subqueries) something like this.
SELECT u.user_id, u.userName, p.num postcount, l.num likecount
FROM UserInfo u
LEFT JOIN (
SELECT COUNT(*) num,
user_id
FROM Post
GROUP BY user_id
) p ON u.user_id = p.user_id
LEFT JOIN (
SELECT COUNT(*) num,
user_id
FROM LikePost
GROUP BY user_id
) l ON u.user_id = l.user_id
What's going on here? The two subqueries, for example
SELECT COUNT(*) num,
user_id
FROM LikePost
GROUP BY user_id
each generate a virtual table with either zero or one row per user_id, showing a count for each user_id. You then join those virtual tables to your UserInfo table.
Use LEFT JOIN because ordinary innner JOIN will suppress users that lack either posts or likes.
Try This
SELECT ui.userName,Count(p.*),
Count(lp.*) as TotalPostLikes
FROM UserInfo ui
INNER JOIN Post p on p.user_id=ui.user_id
INNER JOIN LikePost lp on lp.user_id=ui.user_id
WHERE ui.user_id = '123'
GROUP BY ui.userName
If you want to select Username, Post and Likes on post, try the following
SELECT ui.userName,p.postContent as PostContent,
(SELECT COUNT(lp.user_id) FROM LikePost lp
WHERE lp.user_id=ui.user_id) as Likes,
(SELECT COUNT(_p .user_id) FROM Post _p
WHERE _p .user_id=ui.user_id) as TotalPosts
FROM UserInfo ui
INNER JOIN Post p on p.user_id=ui.user_id
WHERE ui.user_id = '123'
Yes you can do it within one query using leftjoin on Post and LikePost like below
SELECT COUNT(*),User.userName FROM UserInfo as User
leftjoin Post as Post on Post.user_id = User.user_id
leftjoin LikePost as LikePost on LikePost.user_id = User.user_id
where Post.user_id = 123
group by Post.user_id

Sql query correction one to many tables

I have two tables one is users and second is user_education.One users can have more than one education listing so i want to get the latest user education listing
users
===============
1-id
2-email
member_experience
==============
1-id
2-user_id
3-designation
user id 1 has 4 enteries in user_education so i want to get the last record enter designation of the user
original full query is like this
SELECT u.id,u.name,u.gender,u.email,file_managed.file_name,file_managed.file_path
from users as u
INNER JOIN member_experience on (SELECT uid FROM member_experience where member_experience.uid=u.id ORDER BY id DESC LIMIT 1)=u.id
LEFT JOIN file_managed on file_managed.id= u.fid
where u.user_type ='individual' AND u.gender='male'
"INNER JOIN member_experience on (SELECT uid FROM member_experience where member_experience.uid=u.id ORDER BY id DESC LIMIT 1)=u.id "
this portion has problem as users has many record in member_experience table but i want to get only one which is latest.
thanks
Devolve the acquisition of the last record to the where statement.
drop table if exists member_experience;
create table member_experience(id int auto_increment primary key, userid int);
insert into member_experience (userid) values
(1),(2),(1);
select * from member_experience
SELECT u.id,m.id
from users as u
join member_experience m on m.userid = u.id
where m.id = (SELECT max(m.id) FROM member_experience m where m.userid = u.id)
order by u.id
Or if you want to include those with no experience
SELECT u.id,m.id
from users as u
left join member_experience m on m.userid = u.id
where (m.id = (SELECT max(m.id) FROM member_experience m where m.userid = u.id)
or m.id is null)
and u.id < 4
order by u.id

Mysql join from multiple tables

I have 3 tables
friends
posts
members
friends
========
id, to, from (user_id's), status
there are 3 status's -1 = denied, 0 = no response/new, 1 = accepted
posts
=======
p_id, user_id (same as member_id), text
members
========
member_id, f_name, l_name
If like to select the text from the post in 'posts' combine it with the users name from 'members' and only display posts where the user_id is in the 'friends' table.
I would like to know if it can be done, I've tried an IN () statement in my query which worked, but it creates a new problem with generating the csv inside the IN (). I'd perfer to do this through mysql, but if it can't be done I may use a global variable to store friend data (but then it will not be upto date or will have to be refreshed when a user gets a new friend).
As I understand it, you want to find the name and posts of all your friends, not any friend that's in the friend table at all...?
Your own user id being in $myId, this should do it (newest posts first);
EDIT: Added status check for friends
SELECT m.f_name, m.l_name, p.`text`
FROM members m
JOIN posts p
ON m.member_id = p.user_id
JOIN friends f
ON f.`to` = m.member_id OR f.`from` = m.member_id
WHERE (f.`from` = $myId OR f.`to`= $myId)
AND f.`status` = 1 AND m.member_id <> $myId
ORDER BY p.p_id DESC
Try this :
SELECT p.text,m.f_name,m.l_name FROM posts p
LEFT OUTER JOIN members m ON p.user_id=m.member_id
where p.user_id in(select id from friends);
OR
SELECT p.text,m.f_name,m.l_name FROM posts p
LEFT OUTER JOIN members m ON p.user_id=m.member_id
INNER JOIN friends f on p.user_id=f.id
If I understand correctly, you have a user_id and you want all the posts authored by "friends" of that user. This query starts at posts, joins that to friends (where the author is the "destination" of the friendship) (at which point the WHERE clause will filter out any non-friend posts), and then joins in members to fill out the author's name info.
SELECT
posts.p_id
posts.text,
CONCAT(members.f_name, " ", members.l_name)
FROM
posts
JOIN friends ON posts.user_id = friends.to
JOIN members ON posts.user_id = members.member_id
WHERE
friends.from = ?
GROUP BY posts.p_id
I added a subquery to get all your friends since I assumed that if you have these records
Friends
==================================
ID TO FROM STATUS
==================================
1 1 2 1
2 3 1 1
and your member_id = 1, your friends are 2, 3. right?
SELECT b.f_name,
b.L_name,
c.`text`
FROM
(
SELECT `to` friendID
FROM friends
WHERE `status` = 1 AND
`from` = ? -- change this to your ID
UNION
SELECT `from` friendID
FROM friends
WHERE `status` = 1 AND
`to` = ? -- change this to your ID
) a INNER JOIN members b
ON a.friendID = b.member_ID
LEFT JOIN posts c
ON a.friendID = c.user_id

mySql Select last entry for each user

I have two tables:
users:
user_id user_name
data:
user_id user_data user_time
I wan to select the latest entry from the data table, but return the user_name, user_id, user_data and user_time.
I have tried the following query, but it returns the first entry, not the last for each user:
sql = "SELECT users.user_name, users.user_id, data.user_data, data.user_time
FROM users
INNER JOIN data ON data.user_id = users.user_id
GROUP BY users.user_name
ORDER BY data.user_time DESC";
Use GROUP BY and MAX, WHERE...IN:
SELECT u.user_id, u.user_name, d.user_data, d.user_time
FROM users u
INNER JOIN data d ON d.user_id = u.user_id
WHERE (d.user_id, d.user_time) =
(SELECT user_id, MAX(user_time) FROM data GROUP BY user_id)
I think you had better add data_id column to data table.
Unless data_id, both user_id and user_time are necessary for PRIMARY KEY(and user_time is not always unique, not reliable)
If there is data_id, it can be bitly simple:
SELECT u.user_id, u.user_name, d.user_data, d.user_time
FROM users u
INNER JOIN data d ON d.data_id =
(SELECT data_id FROM data
WHERE user_id = u.user_id ORDER BY data_time DESC LIMIT 1)