I have a data structure where students and groups have many-to-many relationship. I have three tables
students: id, name
groups: id, name
students_groups: student_id, group_id
How do I select only students who are not in a specific group (e.g. group.id = 1)?
I did some searching and tried using sub query but only get an empty set...
select * from students where not exists (select students.* from students left join students_groups on students_groups.student_id = student.id where students_groups.group_id = 1);
how should I query? thx much in advance!
EDIT
OK, it seems the following two finally works... can anyone EXPLAIN to me why I don't need to join table for it to work???
select * from students where not exists (select * from students_groups where students_groups.student_id = student.id and student_groups.group_id = 1);
select * from students where id not in (select student_id from students_groups where group_id = 1);
Using a NOT IN should work fine:
SELECT * FROM Students
WHERE Id NOT IN (
SELECT Student_Id FROM Students_Groups
WHERE Group_Id = 1)
The edited question asks for an explanation.
Think of SQL queries as Venn Diagrams in text. Each clause either defines a circle of content, or tells you which part of the full overlapping circles diagram you're interested in.
select * from students where id not in (select student_id from students_groups where group_id = 1);
One circle is the students table. One circle is the student_groups table where group_id = 1. The circles overlap where students.id equals student_groups.student_id. You want the part of the students table that is not in the overlap area.
You don't need to join the tables because your result set contains data only from the students table. You are using the other table to limit that result set, not provide data to your results.
Untested, but one of the following ought to work. You'll have to do some explaining and see which one is best.
select *
from students
where not exists (select *
from students_groups
where students_groups.student_id = student.id
and students_groups.group_id = 1)
or...
select *
from students
where id not in (select student_id
from students_groups
where group_id = 1)
or...
select students.id, students.name
from students
left outer join students_groups on students.id = students_groups.student_id
and students_groups.group_id = 1
where students_groups.student_id is null
group by students.id, students.name
You could try something like this:
SELECT
*
FROM
students
WHERE
id NOT IN
((SELECT
student_id
FROM
students_groups
WHERE
group_id = 1
))
Related
table posts
table users
how would i count posts for specific user logged in. for example when user with id 3 is logged in it should show me 4 posts
I already did it for total posts count:
<?php
$post_query1 = "SELECT count(*) AS total FROM posts ";
$post_result1 = mysqli_query($db, $post_query1);
$post1 = mysqli_fetch_array($post_result1);
?>
Try below example :
select count(*) as total from user as u inner join post as p on p.id_user = u.id_user AND u.id_user = 3
If you want to get only the posts count for the particular user, say user with id = 3, your query should be this:
$query = "SELECT count(*) AS total FROM posts WHERE id_users = 3";
But if you want to get both the posts count as well as the user information and other post information, you will have to run a join query on both the users and posts table. Your query would now become:
$query = "SELECT u.*, p.*, count(p.id_posts) FROM users AS u JOIN posts AS p ON u.id_users = p.id_users WHERE p.id_users = 3";
Some Useful Notes
p.* - * is a wildcard character that means get all the columns in the posts table
u.* - * is a wildcard that means get all the columns in the users table
posts as p - AS is for aliasing. So, we are giving posts table a temporary name.
Here are the different types of the JOINs in SQL:
(INNER) JOIN: Returns records that have matching values in both tables
LEFT (OUTER) JOIN: Return all records from the left table, and the matched records from the right table
RIGHT (OUTER) JOIN: Return all records from the right table, and the matched records from the left table
FULL (OUTER) JOIN: Return all records when there is a match in either left or right table
Note: It is necessary that you have to join two/more tables only with the help of foreign key. Without the foreign key is is meaningless to join two or more tables
Reference 1: https://www.w3schools.com/sql/sql_join.asp
Reference 2: https://www.tutorialspoint.com/mysql/mysql-using-joins.htm
As per the Question what you have asked to join the tables
Query:
SELECT * FROM TABLE 1 JOIN TABLE 2 ON TABLE1.id = TABLE2.id WHERE TABLE2.ID=3
Kindly replace TABLE1 & TABLE2 with the Tables that are to be joined and the id with the foreign key what you have specified in the Table.
Hope so this might be helpful for you to write your own code in future. Happy Coding :)
You have only to use a simple join.
SELECT count(*)
FROM USER u,
post p
WHERE p.id_user = u.id_user
AND u.id_user = 3
First post, be gentle! My SQL knowledge is average, at best.
I have 2 tables with no direct relationship to each other.
TableA ("CustomerWishList") with columns "bookID", other-book-data,
etc etc etc
TableB ("CustomerOwned") with columns - "bookID", other-book-data, etc etc etc
A book could be in one, both, or none of those tables.
I need to create SQL statement that counts the number of "bookID='data'" occurrences in either TableA or TableB.
So far using PHP I'm searching TableA "bookID" column first, and then if nothing found, searching TableB "bookID" column next ... it works, but is inefficient, and am convinced there must be a better way.
JOIN statements don't seem to apply here? - I could be wrong.
UPDATED
Psuedo PHP code I'm currently using:
$total=SELECT COUNT(*) FROM CustomerWishList WHERE BOOKID=1234
if ($total==0) {
$total2=SELECT COUNT(*) FROM CustomerOwned WHERE BOOKID=1234
}
return $total2;
Below query would give you count of book ids which are only in table A:
SELECT count(1) as `count`
FROM tableA
WHERE NOT EXISTS
(SELECT bookID FROM tableB WHERE bookID = tableA.bookID);
Similarly, following query would give you count of book ids which are only in table B:
SELECT count(1) as `count`
FROM tableB
WHERE NOT EXISTS
(SELECT bookID FROM tableA WHERE bookID = tableB.bookID);
Now, if you want to add these two then you can use the following query:
SELECT `a.count` + `b.count`
FROM (
SELECT count(1) as `count`
FROM tableA
WHERE NOT EXISTS
(SELECT bookID FROM tableB WHERE bookID = tableA.bookID)
) a,
(
SELECT count(1) as `count`
FROM tableB
WHERE NOT EXISTS
(SELECT bookID FROM tableA WHERE bookID = tableB.bookID);
) b;
I'm using Sqlsrv and I need to find common values within the same table using PHP. There are two main columns, user_id and bssid.
Using a selected $user_id, I need to find all common "bssid" values and return a set of users which contain these values (this is if another user_id has one or more bssid the same).
This is my query string so far. My logic doesn't work.
$sql = "SELECT A.* FROM AccessPoints A INNER JOIN (SELECT bssid, user_id
FROM AccessPoints WHERE user_id='$userID'
GROUP BY bssid, user_id
HAVING COUNT(*) >= 1) B
ON A.bssid = B.bssidB.user_id = A.user_id";
The database schema is as such:
A sample of the dataset can be seen as such, and contains the data from two users:
I simply want to query a user_id and return all other user_ids which have similar bssids
If you want all the user_id including the the one you are searching on then:
SELECT user_id
FROM AccessPoints
WHERE bssid IN(SELECT bssid
FROM AccessPoints)
WHERE user_id = '$userID')
If you want to exclude the one you are searching from the output then:
SELECT user_id
FROM AccessPoints
WHERE bssid IN(SELECT bssid
FROM AccessPoints)
WHERE user_id = '$userID')
AND user_id != '$userID'
How can i select all the id's from a table, and let select all the songs with the id;s from the other table?
$query = "SELECT * FROM songs WHERE id = (SELECT songid FROM top10 order by id)'";
You can use IN for that (or EXISTS):
select *
from songs
where id in (
select songid
from top10 )
Based on your comments, you might actually be looking to use JOIN (just realize if there are duplicate records in the top10 table, this could return duplicate results):
select s.*
from songs s
join top10 t on s.id = t.songid
order by t.id
SQL Fiddle Demo
I am trying to join my users table with another table using the following query...
SELECT * FROM (`activities`)
JOIN `users` ON `users`.`id` = `activities`.`user`
WHERE `user_subdomain` = 'hi' OR user_subdomain = ''
ORDER BY `activities`.`id` desc
LIMIT 10
Is there any way to do the join so that the id of the user does not replace the id of the activity?
For example, currently if there is an activity with the id of 10 and the user 2 the id will be replaced by the id of the users table and show as 2 after I run the query.
Thanks a lot for the help!
Whenever you are joining tables, you ought to be explicit about the columns you select rather than using SELECT *, and specify column aliases for them when the same column name is used in multiple tables.
SELECT
activities.id,
activities.othercol,
/* Alias to userid */
users.id AS userid,
users.name,
users.anothercolumn
FROM (`activities`)
JOIN `users` ON `users`.`id` = `activities`.`user`
WHERE `user_subdomain` = 'hi' OR user_subdomain = ''
ORDER BY `activities`.`id` desc
LIMIT 10
Though it isn't strictly necessary to prepend the table name to each, unless the column names are the same.
SELECT
activities.id AS activityid,
othercol,
users.id AS userid,
name,
anothercolumn