select rows in mysql database based on associations in another table - php

I am using PHP and MySQL.
I have a table user_groups with the following fields
id, userID, groupID
A user can be associated with many groups, so if I selected from this table a particular userID then I could come up with several groupID's
I have another table group_messages with the following fields
id, groupID, message
If I want to select all of the messages from the group_messages table whose groupID is associated with a particular userID, how can I write this query? I first need to select all of the groupID's from the user_groups table where the userID is a particular id and then select all of the messages from the group_messages where the groupID is any that I have selected from the user_groups table.
Therefore, I can select all of the groupID's from the user_groups table by:
SELECT * FROM user_groups WHERE userID = '3'
This will return a range of groupID's
Then I need to select only those messages in the group_messages table where the groupID is within the set of numbers I have grabbed from the user_groups table.
Is there a way to do this with one query? I thought that maybe I could create an array of the groupIDs from the user_groups table and then dynamically with a foreach statement generate the sql query like:
$sql = "SELECT * FROM group_messages WHERE (";
foreach ($groupID_array as $v){
$sql .= "(groupID = '$v')or";
}
$sql = rtrim($sql, 'or');
$sql .= ")";
The problem with this method is that there could be thousands of groups a user is associated with, which would make this code run very slow and time out. Is there another way to do it with one query?

Use the IN operator:
SELECT * FROM group_messages WHERE groupID IN (1,2,3,4);
As 9000 mentioned below, you can make this in a single query like this:
SELECT * FROM group_messages
WHERE groupID IN (SELECT groupID FROM user_groups WHERE userID = '3')

Related

Using Order By with Union - SQL Statement

I have a database with direct messages from one user to another.
Table name: dm
id int(11) Primary Key
to: varchar
from: varchar
message: varchar
I have a SQL Statement that selects the distinct values from the to and from column as if they were one column. ($username is a session variable)
"SELECT DISTINCT from
FROM dm
WHERE to = '$username'
UNION
SELECT DISTINCT to
FROM dm
WHERE from = '$username'
";
I am checking to see if this user has received or sent any messages basically. I want to ORDER BY id of dm. How can I change my code so I get the same results and it orders by id DESC? If I simply enter ORDER BY like so, I get an error because I didn't select it... Thank you so much for the help
"SELECT DISTINCT from
FROM dm
WHERE to = '$username'
UNION
SELECT DISTINCT to
FROM dm
WHERE from = '$username'
ORDER BY id DESC
";
If I got exactly what you wanted to do you should keep things separate:
1st step: your original code, plus the user ID added to the dataset
CREATE TABLE new_table_name AS
SELECT DISTINCT ID, from
FROM dm
WHERE to = '$username'
UNION
SELECT DISTINCT ID, to
FROM dm
WHERE from = '$username';
2nd step: order by ID
CREATE TABLE ordered_table AS
SELECT *
FROM new_table_name
ORDER BY ID DESC;

SQL get common values in a database

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'

MySQL inner join 2 tables to match user number to user name

I'm sorry this has probably been answered hundreds of time but I'm totally lost between different scenarios here.
What I want is pretty simple. I have 2 tables "bets" and "users".
In the table "bets", I put the UserID instead of the UserName. In the table "users", the UserName is linked to the UserID.
I would like to be able to read the data from the table "bets" and display the UserName instead of the UserID, so I will need some sort of code to match the UserID contained in the table "bets" and return the UserName instead.
The MySQL query I have for now:
$sql5="SELECT * FROM Bets, Users WHERE GameID = '$NGnumber' ORDER BY DrawOrder";
$result5 = mysql_query($sql5) or die(mysql_error());
while($rows5 = mysql_fetch_assoc($result5)){
...
I can easily echo $rows5['UserID'] but I would like the UserName (in the Users table) instead. How can I do that?
Thanks!
Use inner join:
SELECT * FROM Bets INNER JOIN Users ON Bets.userID = Users.userID WHERE GameID = '$NGnumber' ORDER BY DrawOrder
Replace the query:
SELECT * FROM Bets b INNER JOIN Users u
ON b.GameID = u.GameID
WHERE GameID ='$NGnumber' ORDER BY DrawOrder"

mysql select rows not in many-to-many relation

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
))

Mysql Join without replacing value of original id

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

Categories