Find records which are not exists in other table - mysql

I've this table structure:
-request
request_id
user_id
-user
user_id
company_id
-company
company_id
I want to select all those records from requests table where user_id=? and no such records where the company id of to users is same.

This is usually achieved using LEFT JOIN:
SELECT r.*
FROM request r
JOIN user u ON r.user_id = u.user_id
LEFT JOIN u1 ON u1.user_id != u.user_id AND u1.company_id = u.company_id
LEFT JOIN request r1 ON r1.user_id = u1.user_id
WHERE r1.user_id IS NULL
By "where" we say that we don't want "users with same company, who has at least 1 request"

Related

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

Convert Sub-query into Joins

I am trying to convert below query via Joins,
SELECT DISTINCT req.*
FROM request req
WHERE (req.user_id IN (
SELECT id from user where id in (SELECT user_id FROM team_member team WHERE team.team_id IN ('344', '723')) and user.active = 1
)
OR req.user_id IN (
SELECT id from user where id in (SELECT approved_employee_id from approver where approver_id = '269') and user.active = 1
))
AND req.status = 'pending';
returns 124 records.
I have wrote below query via joins but doesn't work,
SELECT DISTINCT req.*
FROM request req
LEFT JOIN user u ON u.id = req.user_id AND u.active = 1
LEFT JOIN team_member team ON team.user_id = u.id AND team.team_id IN ('344', '723')
LEFT JOIN approver app ON app.approver_id = u.id AND app.approver_id = '269'
AND req.status = 'pending';
returns more than 500 records.
two issue with this joins, it includes those requests too where status is not pending.
Below is the schema
I have below tables
tbl_approver =
id,
approver_id (FK tbl_user),
approver_team_id (FK tbl_team),
approved_employee_id (FK tbl_user)
tbl_team_mambers =
id,
team_id (FK),
user_id (FK)
tble_user =
id,
email,
username
active
tbl_request =
id,
user_id,
status
Teams Members : A user is a member of multiple teams.
Approver :
For each team there is an approver, who is also the member of that team.
there can be direct approver of an employee regardless of team.
request : inventory requests by the user
Note : as an approver, i can be member of many teams but only approver
of some team. or some employee too.
Query wanted : as an approver i want all request of my teams whom i am approver.
For correct results of join's you need to any joined "table" return only one row for user_id. And do not use left if needed only rows existing in all tables.
SELECT req.*
FROM request req
JOIN user ON user.id=req.user_id
JOIN (
SELECT distinct approved_employee_id as user_id from approver where approver_id = '269'
UNION
SELECT distinct user_id FROM team_member team WHERE team.team_id IN ('344', '723')
) A ON req.user_id=A.user_id
where user.active = 1
AND req.status = 'pending';
Or, if needed only "real table":
SELECT DISTINCT req.*
FROM request req
JOIN user u ON u.id = req.user_id AND u.active = 1
LEFT JOIN team_member team ON team.user_id = u.id AND team.team_id IN ('344', '723')
LEFT JOIN approver app ON app.approver_id = u.id AND app.approver_id = '269'
WHERE req.status = 'pending'
AND (team.user_id is not null OR app.approver_id is not null)
Watch the LEFT JOIN syntax, here's the visual expression of joins
SELECT DISTINCT req.*
FROM request req
LEFT JOIN user u ON u.id = req.user_id AND u.active = 1
...
This will select all distinct records from request, and JOIN them to user. The join_condition after ON will only affect the join relation.
If there is no matching row for the right table in the ON or USING part in a LEFT JOIN, a row with all columns set to NULL is used for the right table.
Join syntax from Mysql Documentation
If you really want to use LEFT JOIN to filter all record from request, consider moving the condition_expr to WHERE
SELECT DISTINCT req.*
FROM request req
LEFT JOIN user u ON u.id = req.user_id
...
WHERE u.active = 1
AND ...
If you only need request that satisfies the join condition to user, you should consider use Join rather than LEFT JOIN.

SQL query to link two tables returning error

I have two tables as follows
user [ ID , username ]
relationship [ user1_id(FK) , user2_id (FK) , status ]
I am trying to get the username by using either user1_id or user2_id where the status = 1 from relationship table. user1_id and user2_id are both IDs from the user table. The following query is failing and I am not sure where it's going wrong.
SELECT
U.username,
(R.first_user_id, R.second_user_id AS friends)
FROM
user U,
`relationship` R
WHERE (R.`first_user_id` = {$userID} OR R.`second_user_id`)
AND (`status` = 1 AND U.ID = friends)
returns both names of users in a relationship with a status of 1.
this also assumes that if a relationship record exists, both users must be in the user table.
SELECT U1.UserName, U2.username
FROM Relationship R
INNER JOIN USER U1
on R.User1_ID = U1.user_ID
INNER JOIN USER U2
and R.User2_ID = U2.user_ID
WHERE R.Status=1
It looks like you may be trying to get the usernames of all users that have a relationship with a certain specified user, regardless of the order of user IDs in the relationship record. That could be this:
SELECT
U.username,
U.first_user_id,
FROM
user U
JOIN `relationship` R
ON R.first_user_id = U.ID
WHERE
(R.`second_user_id` = {$userID})
AND (`status` = 1)
UNION ALL
SELECT
U.username,
U.second_user_id,
FROM
user U
JOIN `relationship` R
ON R.second_user_id = U.ID
WHERE
(R.`first_user_id` = {$userID})
AND (`status` = 1)
If that produces duplicates (or could do) and you don't want it to do, then change the UNION ALL to a straight UNION.
I have succeeded based on xQbert answer:
SELECT
U1.username,
U2.username
AS user_friend
FROM
Relationship R
INNER JOIN
user U1
ON
R.first_user_id = U1.ID
INNER JOIN
user U2
ON
R.second_user_id = U2.ID
WHERE (R.`first_user_id` = {$userID} OR R.`second_user_id` = {$userID})
AND `status` = 1

SQL join count(*) of one table to another table as aliases

I have two table, users and comments.
In the users table, there're columns id and username.
In the comments table I have user_id and his message.
And I wanted to create a table that select the username and his comment count when I search a particular username.
How do I write this?
my testing attempt:
SELECT COUNT(*) AS comment_count
FROM song_comments
RIGHT JOIN users
WHERE user_id = 7 AND comments.user_id = users.id
Try this:
SELECT U.Username, COUNT(SC.message) AS comment_count
FROM song_comments SC JOIN
users U ON U.id=SC.user_id
WHERE U.user_id = 7
GROUP BY U.Username
This gives you users and count
select u.username, count(c.user_id) as comment_count
from users u
join comments c on u.id = c.user_id
group by u.username
You can add a where to get one user's count
select u.username, count(c.user_id) as comment_count
from users u
join comments c on u.id = c.user_id
where u.username = 'Hogan'
group by u.username

chat application friend list

I have 3 MySQL tables namely chat_comments, chat_friends and user_details and I want to display a friend list.
My tables:
chat_comments(comment_id,comment,user_id,user_id2,date_added)
chat_friends(user_id,user_id2,approved)
user_details(user_id, mainimage_id, fullname)
To do this, I need a query that will return the needed fields (u.mainimage_id, u.fullname, b.comment, b.user_id) so I can loop through the list to display a table.
SQL so far (help from #Andriy M):
SELECT
cc.comment,
cc.date_added,
u.fullname,
u.mainimage_id
FROM
user_details u
LEFT JOIN
chat_comments cc
INNER JOIN (
SELECT
user_id,
MAX(comment_id) AS maxcomment
FROM chat_comments WHERE user_id=2020 OR user_id2=2020
GROUP BY user_id
) a ON a.user_id = cc.user_id
AND a.maxcomment = cc.comment_id
ON a.user_id = u.user_id
WHERE u.user_id IN (
SELECT user_id2
FROM chat_friends
WHERE user_id = 2020
AND approved = 1
)
The above query returns the last comment made by the logged-in user's friends in conversation not the last comment between the logged-in user and his/her friend regardless of who made it.
I would like it to return the last comment between the logged-in user and their friend individually regardless of who made it. In the chat_messages table, user_id is the sender and user_id2 is the receiver. Hope it makes sense?
Like #imm said in a comment, you need to use an outer join. In case of a left join, the user_details table should become the left side of the join, the right side being the result of your inner join of chat_comments with your a derived table. You'll also need to remove the user_id IN (…) condition from inside the a subselect and re-apply it to the user_details table. Here:
SELECT
cc.comment,
cc.date_added,
u.fullname,
u.mainimage_id
FROM
user_details u
LEFT JOIN
chat_comments cc
INNER JOIN (
SELECT
user_id,
MAX(comment_id) AS maxcomment
FROM chat_comments
GROUP BY user_id
) a ON a.user_id = cc.user_id
AND a.maxcomment = cc.comment_id
ON a.user_id = u.user_id
WHERE u.user_id IN (
SELECT user_id2
FROM chat_friends
WHERE user_id = 2020
AND approved = 1
)
;
Alternatively, you could use a right join. In this case you would just need to move the user_id IN (…) condition, similarly to the LEFT JOIN solution above, and replace the second INNER JOIN with RIGHT JOIN:
SELECT
cc.comment, cc.date_added, u.fullname, u.mainimage_id
FROM
(
SELECT user_id, MAX(comment_id) AS maxcomment
FROM chat_comments
GROUP BY user_id
) a
INNER JOIN
chat_comments cc ON
a.user_id = cc.user_id AND
a.maxcomment = cc.comment_id
RIGHT JOIN
user_details u ON
a.user_id = u.user_id
WHERE u.user_id IN (select user_id2 from chat_friends where user_id=2020 AND approved=1)