I have the following tables:
user (id, firstname, lastname)
follow (id, follower_id, following_id)
Now imagine we have users with id 1, 2, 3, 4, 5
And user_id = 1 already following user 2 and 3.
Now I want to write a query that gives me the user_id's that I (user_id = 1) am not following which are (4 and 5).
Can someone please help.
This should do it:
SELECT id FROM user
WHERE
id NOT IN
(
SELECT following_id
WHERE follower_id = 1 --(or you can use any user i, i used 1 to show an example)
)
SELECT * FROM user_table
LEFT JOIN follow_table ON user_table.id = follow_table.following_id
WHERE follow_table.following_id IS NULL
Try this:
SELECT * FROM user_table ut
LEFT JOIN follow_table ft ON ut.id = ft.following_id AND ft.follower_id = 1
WHERE ft.following_id IS NULL
Related
I have two tables, user:
id
full_name
is_admin
1
jane
0
2
Helio
0
3
fran
0
4
mila
0
5
admin
1
approver :
id
subordinate_id
approver_id
1
1
2
2
3
4
and I would like to perform a query that brings up the user names that do not have the id in the subordinate_id column of the approvers table.
I tried it this way:
SELECT
full_name
FROM user AS U
WHERE NOT EXISTS(
SELECT * FROM approver AS A
WHERE A.subordinate_id = U.id AND U.is_admin = 0);
but in this case the admin user is still coming, and I would like to not bring whoever has the is_admin column of the usuario table = 1. I want to bring only common users and not admin.
Can someone help me with this?
Try this query
SELECT full_name FROM user AS U
left join approver as A on U.id = a.subordinate_id
where A.id is null AND U.is_admin = 0
You need to put AND U.is_admin = 0 outside EXISTS
create table `user`(
id int,
full_name varchar(20),
is_admin int
);
create table `approver`(
id int,
subordinate_id int,
approver_id int
);
insert into `user`(id,full_name,is_admin) values
(1,'jane',0),
(2,'Helio',0),
(3,'fran',0),
(4,'mila',0),
(5,'admin',1);
insert into `approver`(id,subordinate_id,approver_id) values
(1,1,2),
(2,3,4);
SELECT
full_name
FROM user AS U
WHERE NOT EXISTS(SELECT A.* FROM approver AS A WHERE A.subordinate_id = U.id )
AND U.is_admin = 0
DB Fiddle Demo
You can try this query. We can select the admin="0" in the first table the can left join on second table. And after that We can do the inverse of inner join to get the results you are expecting.
SELECT fullname
FROM
(SELECT * FROM user WHERE is_admin="0") U
LEFT JOIN Approver A
ON U.id=A.subordinate_id
WHERE A.subordinate_id IS NULL;
The tables are as below:
Users Table (Table Name: users) :
[users table]
Friends Table (Table Name: friends) :
[friends table]
My Sql Code:
SELECT
friend_id,
friend_adding_id,
friend_added_id,
user_id,
user_name
FROM friends
LEFT JOIN users ON friends.friend_added_id = users.user_id
WHERE
friend_adding_id = 1
OR friend_added_id = 1
AND friend_confirm = 1
ORDER BY friends.friend_id DESC
LIMIT 1, 10
Leaving the column below:
[Leaving column]
How can I fix this missing query? Please help me.
first you are missing a row not a column or not a query, second its because of and /or priorities. And has higher priority than OR , for you logic to work properly, you have to give Or higher priority by using parenthesis:
SELECT
friend_id,
friend_adding_id,
friend_added_id,
user_id,
user_name
FROM friends
LEFT JOIN users ON friends.friend_added_id = users.user_id
WHERE
(friend_adding_id = 1 OR friend_added_id = 1) -- < like this
AND friend_confirm = 1
ORDER BY friends.friend_id DESC
LIMIT 1, 10
EDIT: I seemed to have asked this question incorrectly.
I'm trying to find a way to query if a set is available in another set. For example:
SELECT * FROM something
WHERE (1, 3) IN (1, 2, 3, 4, 5)
In this case, 1 & 3 are in the set (1, 2, 3, 4, 5). Another example:
SELECT * FROM something
WHERE (1, 3) IN (1, 5, 7, 9);
In this case, 1 & 3 ARE NOT in the set (1, 5, 7, 9) so nothing should be pulled from the table.
NOTE: This answers the original question, which seems to have nothing to do with the question after OP modifications.
You can get the users who completed all three levels by using:
SELECT cl.user_id
FROM completed_levels cl
WHERE cl.id IN (3, 5, 7)
GROUP BY cl.user_id
HAVING COUNT(DISTINCT cl.id) = 3;
(Note: DISTINCT is not necessary if the ids for a given user are unique.)
THEN, you can get what you want using a JOIN or similar construct:
SELECT u.*
FROM users u JOIN
(SELECT cl.user_id
FROM completed_levels cl
WHERE cl.id IN (3, 5, 7)
GROUP BY cl.user_id
HAVING COUNT(DISTINCT cl.id) = 3
) cu
ON cl.user_id = u.id;
NEW REQUEST (according to sqlfiddle.com/#!9/f36d92/2):
# The goal is to write a query that will select all exercises
# that the user has the correct equipment for, where the pre-defined
# set is the id's of the equipment the user has.
# For example, let's assume the user has equipment (1, 4)
# The exercise "Curls" should be pulled from the table, as the user has all
# of the required equipment based on the exercise_requirements table.
# while "Wrecking Ball" is not returned as the user only has a portion of the
# required equipment.
# If the user's equipment was (1, 3, 4) then both "Curls" and "Wrecking ball"
# would be returned from the exercises table, as the user has the required equipment
# for both exercises.
#----
#Below is my take on your query.
SELECT ex.* FROM exercises ex
WHERE ex.id IN (
SELECT exercise_id FROM exercise_requirements
WHERE ex.id IN (1, 4)
GROUP BY exercise_id
HAVING COUNT(distinct exercise_id) = 3
);
SOLUTION:
You are confusing some IDs here. This would be closer:
SELECT ex.* FROM exercises ex
WHERE ex.id IN (
SELECT exercise_id FROM exercise_requirements
WHERE equipment_id IN (1, 4)
GROUP BY exercise_id
HAVING COUNT(distinct equipment_id) = 2
);
But still this query is vice versa. We don't want to know whether all the user's equipment are found in a set of equipment needed for an exercise, but whether the whole set of equipment needed for an exercise is found in the user's equipment.
Probably the easiest way to write this is: aggregate exercise_requirements per exercise_id and check that no equipment_id is needed that the user doesn't have.
select *
from exercises
where id in
(
select exercise_id
from exercise_requirements
group by exercise_id
having sum(equipment_id not in (1, 4)) = 0
);
Your updated fiddle: http://sqlfiddle.com/#!9/f36d92/5
You are using the IN clause with a correlated subquery (i.e. the subquery references u.id). This is not how we use it. The IN clause is great for non-correlated subqueries; if you need a correlated subquery, use EXISTS instead. For your problem a non-correlated subquery suffices, so use IN accordingly:
select *
from users
where u.id in (select user_id from completed_levels where id in (1, 5, 7);
If a user must have all levels:
select *
from users
where u.id in (select user_id from completed_levels where id = 1
and u.id in (select user_id from completed_levels where id = 5
and u.id in (select user_id from completed_levels where id = 7;
Such problems are usually better solved with an aggregation so as not to have to query the same table again and again:
select *
from users
where u.id in
(
select user_id
from completed_levels where id in (1, 5, 7)
group by user_id
having count(distinct id) = 3
);
You could use this
SELECT u.*
FROM users u
INNER JOIN completed_levels cl
ON cl.user_id = u.id
WHERE cl.id IN (1, 5, 7);
Or using EXISTS as link from #DanFromGermany
You can use Case to make a Sum which will increase with 1 for each level within 1, 5 & 7.
SELECT A.* FROM users AS
INNER JOIN
(
SELECT U.id,
SUM(CASE WHEN
(
A.completed_levels = 1
OR A.completed_levels = 5
OR A.completed_levels = 7
) THEN 1 ELSE 0 END
) AS RN
FROM completed_levels A
INNER JOIN users U ON A.user_id = U.id
GROUP BY U.id
) B ON A.id = B.id
WHERE B.RN = 3 -- Those users have completed level 1, 5 & 7 will have RN = 3 only
Have tables: person,person_ip
Both tables have pid column as a primary key, in table person there is column state_id, in table person_ip there is column ip.
Want to discover if specified IP address is assigned to person with state_id is not equal to 2. But always got result 1, even if state_id is 0, 1 or 2. Always got 0 only if ip address is not listed at all. What am I doing wrong?
SELECT EXISTS (
SELECT person_ip.PID
FROM person_ip,person
WHERE person.PID=person_ip.PID
AND person.state_id NOT IN (2)
AND person_ip.ip='10.11.12.13'
)
this seems like a simple join.. unless i'm missing something
select person.*
from person
inner join person_ip
on person.pid = person_ip.pid
where person.state_id <> 2
and person_ip.ip_address = '10.0.0.1'
If you want to exclude the ip_address if it has been assigned to any user with state = 2, even if it has also been assigned to a user without state = 2, then try:
select max(i)
from (
select *
from (
select 1 as i
from dual
where not exists (
select 1
from person p
inner join person_ip pi
on p.pid = pi.pid
where p.state_id = 2
and pi.ip_address = '10.0.0.1'
)
) q
union
select 0
) qq
(dual is a system table that can be used as a sort of stub table)
here's a fiddle showing both versions
update after some actual sleep
Okay, so the above query is a little.. out there. Back in the real world, this one is probably more appropriate:
select count(case when p1.state_id = 2 then 1 end)
from person p1
inner join person_ip pi1
on p1.pid = pi1.pid
where pi1.ip_address = '10.0.0.1'
group by pi1.ip_address;
This will return 1 or more if your ip_address has been used by someone with a state_id of 2, and 0 if it has never been used by someone with a state_id of 2.
It will return nothing if the ip has never been used.
this fiddle has all three of the above queries.
SELECT IF(COUNT(*)>0,1,0)
FROM person
INNER JOIN person_ip
ON person.pid = person_ip.pid
AND person_ip.ip_address = '10.0.0.1'
WHERE person.state_id <> 2
I have two tables. One is named usertbl with columns user_id, user_name, and acct_status. possible values for acct_status values are 0, 1, 2, 3. Another table named accountstatustbl has the following columns - acct_status, and acct_status_desc, with values when acct_status = 0, acct_status_desc = enrolled, 1 = active, 2 = inactive, and 3 = deactivated. Now, how should I query my db to provide me the following output:
user_id user_name status
0000000 user1 enrolled
1234567 user2 active
9999999 user3 deactived
instead of giving me values 0, 1, and 3?
You can try this.
SELECT user.user_id, user.user_name, status.description
FROM usertbl user left outer join accountstatustbl status
on user.acct_status=status.acct_status
SELECT u.user_id, u.username, s.acct_status_desc status
FROM usertbl u, accountstatustbl s
WHERE u.acct_status = s.acct_status
Hope I helped.
you can use INNER JOIN assuming that acct_status in usertbl has no NULL values:
SELECT a.user_id,
a.user_name,
b.status_desc AS status
FROM usertbl a
INNER JOIN accountstatustbl b
ON b.acct_status = a.acct_status
you can also read about MySQL JOIN Syntax to understand more about joins