MySql how to combine LEFT JOIN query with NOT IN query - mysql

I need to combine LEFT JOIN query with NOT IN query and have to get the result values from these queries. I have get the correct results while using these two queries at separately.
I have two tables likely user and answer
user table
user_id
1
2
3
4
5
answer table
user_id date
1 2015-10-15 21:23:14
2 2015-10-15 20:23:14
3 2015-11-11 16:23:14
LEFT JOIN query:
SELECT user.user_id
FROM user
LEFT JOIN answer
ON user.user_id = answer.user_id
WHERE DATEDIFF(NOW(),answer.date) > 5
This query returns result user_id 1,2.
NOT IN query:
SELECT user.user_id
FROM user
WHERE user.user_id NOT IN (SELECT answer.user_id FROM answer)
This query returns result user_ids 4, 5.
I need to combine this two queries into single query so I tried with these two below queries:
SELECT user.user_id
FROM user
LEFT JOIN answer
ON user.user_id = answer.user_id
WHERE (DATEDIFF(NOW(),answer.date) > 5
AND user.user_id NOT IN (SELECT answer.user_id FROM answer))
and
SELECT user.user_id
FROM user
LEFT JOIN answer
ON user.user_id = answer.user_id
WHERE user.user_id NOT IN (SELECT answer.user_id FROM answer)
AND DATEDIFF(NOW(),answer.date) > 5
But these return empty user_id.
Edit
Expected result should contain values of 1,2,4,5

If your meaning is about to combine 2 selection together Try Union All / Union :
SELECT * FROM
(
SELECT [WITH YOUR LEFT JOIN STATEMENT]
UNION
SELECT [WITH YOUR NOT IN STATEMENT]
) ResultTABLE

If you refer to the answer table in the WHERE clause, the answer.date will be restricted to non-NULL value, making the LEFT JOIN behave like a regular join. Move the condition to the ON condition to retrieve all the users, plus maybe the matching rows in answers:
SELECT user.user_id
FROM user u
LEFT JOIN answer a ON u.user_id = a.user_id
AND DATEDIFF(NOW(),a.date) < 5
;
Edit: after the edit of the question it appears the OP wants joined records with non existing answer OR answer.date too old/young:
SELECT user.user_id
FROM user u
LEFT JOIN answer a ON u.user_id = a.user_id
WHERE a.date IS NULL -- no answer record
OR DATEDIFF(NOW(),a.date) > 5 -- too old answer record
;
Final version: Since the OP wants to find users who don't have a (recent) answer, the query can be simplified to:
SELECT user.user_id
FROM user u
WHERE NOT EXISTS (
SELECT * FROM answer a
WHERE a.user_id = u.user_id
AND DATEDIFF(NOW(), a.date) <= 5
);

Related

MYSQL COUNT with SELECT condition

Im newbie please help me on my project. I have 2 tables below.
Table user:
Table Likes
I want to count all likes per story_id and check if the given user has like the story else it will return null.
as of now this is my query and output, given user id = 1.
SELECT COUNT(*) , sl.story_id, u.id as user
FROM stories_likes sl
LEFT JOIN users u ON sl.user_id = u.id AND sl.user_id = 1
GROUP BY sl.story_id
My output:
But what i want to get output is:
Given: user_id = 1
Given user_id = 4
Sorry for the construction of my question i dont know how. Thanks in advance
If the query should display the result for a one particular user_id only then try the following query:
select count(*),
story_id,
(case find_in_set(1, Group_concat(user_id separator ',')) >0 then 1
else NULL
end
)as user_id
from Stories_Likes
group by story_id;
In above query, you can put user_id manually after when, or you can set a variable with particular Id and use it in the query.
For i.e., if you want to check for user_id=4, then put 4 after when and then.
Click here for the Updated Demo
Hope it helps!
The users table is left joined to the query, so it may have null values. Instead, you should use the user_id column from the stories_likes table:
SELECT COUNT(*) , sl.story_id, sl.user_id as user
-- Here --------------------------^
FROM stories_likes sl
LEFT JOIN users u ON sl.user_id = u.id AND sl.user_id = 1
GROUP BY sl.story_id
Got the answer. for those who has the same problem and needed this here's the answer.
SELECT COUNT(*) , sl.story_id, t.user_id
FROM stories_likes sl
LEFT JOIN users u ON sl.user_id = u.id
LEFT JOIN (SELECT * FROM stories_likes WHERE user_id = 4) t ON
sl.story_id = t.story_id
GROUP BY sl.story_id
Where the given user is declared on temporary table t

How to use Where before Left Join MySQL

I have two tables that have a structure like this. First the users table:
id | email | password
1 'email' 'pass'
2 'new2' 'pass'
and the report table:
user_id | field | text
1 4 Tom
How can I return back the the email and password values even if the user doesn't have a match in the report table? This is what I have so far.
select a.email, a.password, b.text from users a
left join data b
on a.id = b.user_id
and b.field = 4
and a.id = 2;
Desired output to get info on user with ID of 2:
email | password | text
'new2' 'pass'
I currently don't get anything back with what i've tried so far
Conditions on the first table in a left join go in the where clause. Conditions on the second table go in the on clause:
select u.email, u.password, d.text
from users u left join
data d
on u.id = d.user_id and d.field = 4
where a.id = 2;
The rule might seem arbitrary at first. However, it is not. The left join returns all rows in the first table regardless of whether the on clause evaluates to true. Hence, a filtering condition on the first table does not filter out any rows. The where clause does this filtering.
Try this:
SELECT
u.email
, u.password
, r.text
FROM
users AS u
LEFT JOIN report AS r
ON r.user_id = u.id
WHERE
u.id = 2
I'm not sure you pasted your query into your question correctly, but if I understand what you're after, this should work:
SELECT a.email, a.password, b.text
FROM users a
LEFT JOIN report b ON a.id = b.user_id
WHERE a.id = 2
It isn't clear why you are trying to check for b.field, but if you need to do so, then go ahead an add it to the LEFT JOIN. In general, put conditions in the LEFT JOIN ... ON when you still want rows to be returned, and put conditions in the WHERE clause when they rows should not be returned if the condition isn't met.

Getting No Output When INNER JOIN Is Used Twice In A Query

I am new to SQL Join topic. I don't know why my SQL Query is not working properly. Here is the query:
SELECT * from post
INNER JOIN user ON post.id = user.id
INNER JOIN follower ON user.id= follower.id
WHERE follower.fid = 20 OR user.id < 1000
ORDER BY pid DESC LIMIT 7
If I use this query it works:
SELECT * from post
INNER JOIN user ON post.id = user.id
WHERE user.id < 1000
ORDER BY pid DESC LIMIT 7
But adding another INNER JOIN gave no output.
Update :
I am using 2 INNER JOINS so that I can show data from 3 table if there are no followers in follower table then show data from 2 tables(post and user) only where id in user table is less then 1000.
Its because you probably have no follower on the post:
SELECT * from post
INNER JOIN user ON post.id = user.id
LEFT OUTER JOIN follower ON user.id= follower.id -- changed JOIN type
WHERE follower.fid = 20 OR user.id < 1000
ORDER BY pid DESC LIMIT 7
Remember INNER JOIN only returns if it finds the match in all JOIN conditions. Any condition will fail and you won't get the row.
For example:
You have a post, but the user has no follower. INNER JOIN will skip the row. Here comes the OUTER JOIN! it will give you the user row even when no follower is found.

MySQL - How to select records that match all IN values but in 1 or more tables

Good day, I can't seem to figure out how to do this. I'll first explain my database model:
User (user_id, name)
Job (job_id, name)
UserTopJob (user_id, job_id)
UserOtherJob(user_id, job_id)
A user can setup his top jobs which he likes best. Those values will be saved into UserTopJob by the user_id and the job_id. The user can set some other jobs he likes into UserOtherJob as well.
Now, what I want to do is query out users that match my job search input.
For example, the search input is job_id 1 and 2.
Now I want to query out the users that match BOTH job_id 1 and job_id 2, but it doesn't matter whether they are in the users top or other jobs, or divided between those two tables.
So a user must be returned if:
Both job_id 1 & 2 are in top jobs
Both job_id 1 & 2 are in the other jobs
They have both job_id 1 and 2 but in different tables
The number of input ids can grow and does not have a limit. It must always match ALL input values.
Edit: So, for example if I'm putting job_ids 1 and 2 and 3 into the query, the ids 1 AND 2 AND 3 need to be in the top or other table for that user.
Can anybody please help me create a MySQL-query that can do this and doesn't put too much pressure on db-performance?
Thanks in advance for helping me out here!
You can use UNION for this type of work.
SELECT user_id AS user FROM UserTopJob where job_id in {job_ids}
UNION
SELECT user_id AS user FROM UserOtherJob where job_id in {job_ids};
Try this query:
SELECT u.*
FROM User u
WHERE NOT EXISTS (
SELECT 1
FROM User u0
JOIN Job j ON j.job_id IN (1,2) -- or other list of job ids
LEFT JOIN UserTopJob utj ON utj.user_id = u0.user_id AND utj.job_id = j.job_id
LEFT JOIN UserOtherJob uoj ON uoj.user_id = u0.user_id AND uoj.job_id = j.job_id
WHERE u0.user_id = u.user_id
AND utj.job_id IS NULL
AND uoj.job_id IS NULL
)
Test in on SQL Fiddle
You can do a JOIN between the tables to get the required result like
select u.name as user_name,
j.name as job_name
from `user` u
INNER join usertopjob utj on u.user_id = utj.user_id
inner join userotherjob uoj on u.user_id = uoj.user_id
inner join job j on j.job_id = utj.job_id or j.job_id = uoj.job_id
where j.job_id in (1,2);
Alright, this was a brain buster this evening. Toying around with this for some time I came up with this and it seems to work.
SELECT user_id, SUM(matched) AS totalMatched FROM
(
SELECT uoj.user_id, COUNT(uoj.job_id) AS matched FROM userOtherJob AS uoj
INNER JOIN user AS u ON u.user_id = uoj.user_id
WHERE uoj.job_id IN (1,2)
GROUP BY u.user_id
UNION ALL
SELECT utj.user_id, COUNT(utj.job_id) AS matched FROM userTopJob AS utj
INNER JOIN user AS u ON u.user_id = utj.user_id
WHERE utj.job_id IN (1,2)
GROUP BY u.user_id
) AS t
GROUP BY user_id
HAVING totalMatched = 2
This query counts the matches in the 'other' table, after that the matches in the 'top' table, and sums the totals of both tables. So, the total number of matches (combined from top and other) must be the same value as the number of jobs we're looking for.

Find unique values that do not exist in multiple columns and tables

A misconfigured manual import imported our entire AD into our help desk user database, creating a bunch of extraneous/duplicate accounts. Of course, no backup to restore from.
To facilitate the cleanup, I want to run a query that will find users not currently linked to any current or archived tickets. I have three tables, USER, HD_TICKET, and HD_ARCHIVE_TICKET. I want to compare the ID field in USER to the OWNER_ID and SUBMITTER_ID fields in the other two tables, returning the only the values in USER.ID that do not exist in any of the other four columns.
How can this be accomplished?
Do a left join for each relationship where the right table id is null:
select user.*
from user
left join hd_ticket on user.id = hd_ticket.owner_id
left join hd_ticket as hd_ticket2 on user.id = hd_ticket2.submitter_id
left join hd_archive_ticket on user.id = hd_archive_ticket.owner_id
left join hd_archive_ticket as hd_archive_ticket2 on user.id = hd_archive_ticket2.submitter_id
where hd_ticket.owner_id is null
and hd_ticket2.submitter_id is null
and hd_archive_ticket.owner_id is null
and hd_archive_ticket2.submitter_id is null
How about something like:
SELECT id
FROM user
WHERE id NOT IN
(
SELECT owner_id
FROM hd_ticket
UNION ALL
SELECT submitter_id
FROM hd_ticket
UNION ALL
SELECT owner_id
FROM hd_archive_ticket
UNION ALL
SELECT submitter_id
FROM hd_archive_ticket
)
If I understood you situation I would do this:
SELECT a.id FROM user a, hd_ticket b, hd_archive_ticket c WHERE a.id != b.id AND a.id != c.id
You would want to try something like below. Inner query where I am doing Inner join with other 2 tables, will return only those user id which exist in all 3 tables. Then in your outer query I am just filtering out those ID's returned by inner query; since your goal is to get only those USER ID which is not present in other tables.
select ID
FROM USER
WHERE ID NOT IN
(
select u.ID
from user u
inner join HD_TICKET h on u.ID = h.OWNER_ID
inner join HD_ARCHIVE_TICKET ha on u.ID = ha.SUBMITTER_ID
)