MYSQL Joins to retrieve result - php

I will try to be as explanatory as possible regarding my question. I am using MYSQL/PHP to fetch data from two tables with the structure looking like the following:
table A
+---------+------------+
| userid | username |
+---------+------------+
| 1 | john |
| 2 | doe |
| 3 | lewis |
+---------+------------+
table B
+---------+------------+-----------+
| id |from_userid | to_userid |
+---------+------------+-----------+
| 1 | 1 | 3 |
| 2 | 3 | 2 |
| 3 | 1 | 2 |
| 4 | 2 | 1 |
+---------+------------+-----------+
Am trying to achieve the following:
+---------+------------+----------------------+
| id |sender username| receiver username |
+---------+------------+----------------------+
| 1 | john | lewis |
| 2 | lewis | doe |
| 3 | john | doe |
| 4 | doe | john |
+---------+------------+----------------------+
As you can see, instead of returning the sender or receiver user id, I am returning their username according to Table A.
can I use left or right joins in this scenario? Thanks in advance

Try this
SELECT b.id, sender.username AS sender_username, receiver.username AS receiver_username
FROM tableB AS b
JOIN tableA AS sender ON b.from_userid = sender.userid
JOIN tableA AS receiver ON b.to_userid = receiver.userid

Inner joins would work fine, you just need to do two of them...
Left and right joins are only needed when you want to get all records from one table and some from another table. In this case you have two distinct relationships thus the need for two joins. My MySQL skills are a bit rusty so I don't know if ' or [ are used as separators on the table/field names with spaces.
Select t1.ID, T1.userName as 'Sender userName', T2.username as 'Receiver username'
FROM [Table A] A
INNER JOIN [Table B] T1
on T1.from_userid = A.userID
INNER JOIN [Table B] T2
on T2.to_userid = A.userID

Related

Select all user who isn't in a team

My database looks something like this, in order of user, userteam (connection table) and team:
Usertable UserTeam Teamtable
+--------+------+ +--------+--------+ +--------+-------+
| userid | name | | userid | teamid | | teamid | name |
+--------+------+ +--------+--------+ +--------+-------+
| 1 | eric | | 1 | 1 | | 1 | awsm |
| 2 | john | | 1 | 2 | | 2 | doe |
| 3 | carl | | 2 | 1 | | 3 | empty |
+--------+------+ | 3 | 1 | +--------+-------+
+--------+--------+
How do I select all users that IS NOT in a team, and echo them out only once? I've tried doing it with the usertable, but then it will echo for instance, if I try and select all members not in team 3:
SELECT userid FROM userteam WHERE teamid!=3;
SELECT * FROM user WHERE userid='$previousSql';
1 eric
1 eric
2 john
3 carl
What I'd like instead is:
1 eric
2 john
3 carl
I'm making an add members function, and I'd very much not like everyone to show up more than once.. Any directions, help or guiding would be much appreciated.
add
GROUP BY name
to the query
This should do it:
SELECT u.userid, u.name FROM Usertable u
INNER JOIN UserTeam ut ON ut.userid = u.userid
INNER JOIN Teamtable tt ON tt.teamid = ut.teamid
WHERE tt.teamid != 3
GROUP BY u.userid, u.name;
SELECT userid, name FROM usertable
JOIN userteam ON userteam.userid = usertable.userid
JOIN teamtable on teamtable.teamid = userteam.teamid
WHERE teamtable.teamid = 3;
The SQL above should do the proper joins between all the tables and then will only list the userid/names of people who have a teamid of 3 in the teamtable
EDIT* Removed ! from WHERE clause.

GROUP BY multiple conditions at once

I have a tables like this:
Users
+----+----------+-------------+
| id | name | other_stuff |
+----+----------+-------------+
| 1 | John Doe | x |
| 2 | Jane Doe | y |
| 3 | Burt Olm | z |
+----+----------+-------------+
Places
+----+------------+-------------+
| id | name | other_stuff |
+----+------------+-------------+
| 1 | Building A | x |
| 2 | Building B | y |
+----+------------+-------------+
Subjects
+----+------------+-------------+
| id | name | other_stuff |
+----+------------+-------------+
| 1 | Math | x |
| 2 | English | y |
+----+------------+-------------+
And a joining table:
PastLectures = lectures that took place
+----+-----------+----------+------------+---------+------------+
| id | id_users | id_place | id_subjects| length | date |
+----+-----------+----------+------------+---------+------------+
| 1 | 1 | 1 | 1 | 60 | 2015-10-25 |
| 2 | 1 | 1 | 1 | 120 | 2015-11-06 |
| 3 | 2 | 2 | 2 | 120 | 2015-11-04 |
| 4 | 2 | 2 | 1 | 60 | 2015-11-10 |
| 5 | 1 | 2 | 1 | 60 | 2015-11-10 |
| 6 | 2 | 2 | 1 | 40 | 2015-11-15 |
| 7 | 1 | 2 | 2 | 30 | 2015-11-15 |
+----+-----------+----------+------------+---------+------------+
I would like to display SUM of all lessons for each user for given month. The SUM should by grouped by each Places and Subjects.
The result in final PHP output should look like this:
November 2015
+------------+-------------+---------------+-------------+
| Users.name | Places.name | Subjects.name | sum(length) |
+------------+-------------+---------------+-------------+
| Burt Olm | - | - | - |
| Jane Doe | Building B | Math | 100 |
| = | = | English | 120 |
| John Doe | Building A | Math | 120 |
| = | Building B | Math | 60 |
| = | = | English | 30 |
+------------+-------------+---------------+-------------+
I have tried creating the full output in pure SQL query using multiple GROUP BY (Group by - multiple conditions - MySQL), but when I do GROUP BY User.id,Places.id it shows each user only once (3 results) no matter the other GROUP BY conditions.
SQL:
SELECT PastLectures.id_users,Users.name AS user,Places.name AS places,Subjects.name AS subjects
FROM PastLectures
LEFT JOIN Users ON PastLectures.id_users = Users.id
LEFT JOIN Places ON PastLectures.id_Places = Places.id
LEFT JOIN Subjects ON PastLectures.id_Subjects = Subjects.id
WHERE date >= \''.$monthStart->format('Y-m-d H:i:s').'\' AND date <= \''.$monthEnd->format('Y-m-d H:i:s').'\'
GROUP BY Users.id,Places.id
ORDER BY Users.name,Places.name,Subjects.name
But I don't mind if part of the solution is done in PHP, I just don't know what to do next.
EDIT:
I also have a table Timetable, that stores who regularly teaches what and where. It stores only used combinations of the tables (each valid combination once).
Timetable = lectures that regularly take place
+----+-----------+----------+------------+-------------+
| id | id_users | id_place | id_subjects| other_stuff |
+----+-----------+----------+------------+-------------+
| 1 | 1 | 1 | 1 | x |
| 2 | 1 | 2 | 1 | y |
| 3 | 1 | 2 | 2 | z |
| 4 | 2 | 2 | 1 | a |
| 5 | 2 | 2 | 2 | b |
+----+-----------+----------+------------+-------------+
Is it possible to add only users with combinations that have a row in this table?
In this case it would mean omitting Burt Olm (no id=3 in Timetable). But if Burt has a Timetable entry and still no PastLectures entry, he would show here as in sample result (he should have had a lecture that month, because he is in Timetable, but no lectures took place).
Based on #Barmar's solution I updated the final SQL by making Timetable a primary table and adding one more LEFT JOIN to suffice those needs.
Final SQL:
SELECT Users.name AS user,Places.name AS places,Subjects.name AS subjects, SUM(PastLectures.length)
FROM Timetable
LEFT JOIN PastLectures ON PastLectures.id_users = Timetable.id_users AND PastLectures.id_place = Timetable.id_place AND PastLectures.id_subjects = Timetable.id_subjects
AND date BETWEEN '2015-11-01 00:00:00' AND '2015-11-30 23:59:59'
LEFT JOIN Places ON Timetable.id_Place = Places.id
LEFT JOIN Subjects ON Timetable.id_Subjects = Subjects.id
LEFT JOIN Users ON Timetable.id_users = Users.id
GROUP BY Timetable.id,Timetable.id_users,Timetable.id_Place,Timetable.id_Subjects
ORDER BY Users.name,Places.name,Subjects.name
You need to include Subjects.id in the GROUP BY, so you get a separate result for each subject.
Also, you shouldn't use columns in tables that are joined with LEFT JOIN in the GROUP BY column. If you do that, all the non-matching rows will be grouped together, because they all have NULL in that column. Use the columns in the main table.
GROUP BY PastLectures.id_users, PastLectures.id_Place, PastLectures.id_Subjects
DEMO
Note that there's no row for Burt Olm in the demo output, because all his rows are filtered out by the WHERE clause. If you want all users to be shown, you should make Users the main table, not PastLectures. And the date criteria needs to be moved into the ON clause when joining with PastLectures.
SELECT Users.name AS user,Places.name AS places,Subjects.name AS subjects, SUM(length)
FROM Users
LEFT JOIN PastLectures ON PastLectures.id_users = Users.id
AND date BETWEEN '2015-11-01 00:00:00' AND '2015-11-30 23:59:59'
LEFT JOIN Places ON PastLectures.id_Place = Places.id
LEFT JOIN Subjects ON PastLectures.id_Subjects = Subjects.id
GROUP BY Users.id, PastLectures.id_Place, PastLectures.id_Subjects
ORDER BY Users.name,Places.name,Subjects.name
DEMO
According to standard SQL, you should GROUP BY all the fields you select, except for the aggregated fields (like sum). Althought MySql allows to do otherwise, when it can be done adhering to the standards, it is better to do so (who knows when you need to port your code to another database engine). So write your SQL like this:
SELECT PastLectures.id_users,
Users.name AS user,
Places.name AS places,
Subjects.name AS subjects,
Sum(length)
FROM PastLectures
LEFT JOIN Users ON PastLectures.id_users = Users.id
LEFT JOIN Places ON PastLectures.id_Places = Places.id
LEFT JOIN Subjects ON PastLectures.id_Subjects = Subjects.id
WHERE date BETWEEN \''.$monthStart->format('Y-m-d H:i:s').'\'
AND \''.$monthEnd->format('Y-m-d H:i:s').'\'
GROUP BY PastLectures.id_users,
Users.name,
Places.name,
Subjects.name
ORDER BY Users.name,
Places.name,
Subjects.name

Mysql query comma separator

I having two tables
table 1: users
| id | username |
| 1 | john |
| 2 | marry |
| 3 | deep |
| 4 | query |
| 5 | value|
and
table 2:users_2
| table_2_id | user_id |
| 1 | 2,4 |
I need required something like this
| table_2_id | username |
| 1 | marry,query |
anyone can help me for this output in mysql
Is this what you are looking ?
select
`users_2`.`table_2_id` , GROUP_CONCAT(`users`.`username`) as `usernames`
from `users_2`
inner join `users` on FIND_IN_SET(`users`.`id`,`users_2`.`user_id`)
Check output here
http://sqlfiddle.com/#!2/c498bc/3
select a.table_2_id,b.username
from users b,users_2 a
where a.table_2_id=b.id
and b.id in(a.user_id)
group by a.table_2_id
First of all, you should not store a multiple value in a single field. For table users_2, the data should be:
table_2_id user_id
1 2
1 4
After you normalized your table, you can use mysql GROUP_CONCAT() to get the result in the format you mentioned
SELECT
users_2.table_2_id,
GROUP_CONCAT(users.username) AS username
FROM
users_2
JOIN
users ON users.id = users_2.user_id
GROUP BY
users_2.table_2_id
;

mySQL: Showing data from one table using id from another

I want my users to be able to make a favourite list.
I have two tables in a database in mySQL. One stores information about businesses and the other stores the unique user ids as well as the ids from the first table that the user has marked a favourite.
Table 1
<pre>
ID | NAME | EMAIL | PHONE |
1 | Joe | a#mail.com | 25634565 |
2 | John | b#mail.com | 43634565 |
3 | Jack | c#mail.com | 65634565 |
4 | James| d#mail.com | 43634565 |
5 | Julie| e#mail.com | 65634565 |
...
</pre>
Table 2
<pre>
USERID | FAV1 | FAV2 | FAV3 | FAV...
2565325489 | 1 | 3 | 5 |
8596854785 | 3 | 2 | NULL |
2356256263 | 5 | NULL | NULL |
...
</pre>
The output I want for a user (in this example the first in table2):
<pre>
Joe | a#mail.com | 25634565 |
Jack | c#mail.com | 65634565 |
Julie| e#mail.com | 65634565 |
</pre>
I have looked into JOIN LEFT and minus query calls, but I just can't make it work. I have a basic understanding of mySQL and PHP, but not a lot.
I would highly appreciate any help with what approach to take.
Ps. If there are better ways to structures my databases, I would love to know.
I'd use a table with two fields - userID and fav - make one entry for each entry. And then...
SELECT table1.name, table1.email, table1.phone FROM table1,table2 WHERE table2.fav = table1.id AND table2.userid = 2565325489
Select * from table1 InnerJoin (Select * from table2) as t4 on table1.ID=t4.FAV1
$result = mysqli_query('SELECT name,email,phone FROM t1 table1 LEFT JOIN table2 t2 ON t1.ID = t2.fav1');
//iterate the results
while ($row = mysqli_fetch_array($result))
{
echo $row['name']." ".$row['email']." "$row['phone'];
}

Query to count values

I have 2 tables in MySQL:
Persons
|ID | Name | Address
---------------------------------
| 1 | Someone | Somewhere
| 2 | Person2 | Somewhere else
And the table ActivePages
|ID | PersonID | Page
---------------------------------------
| 1 | 1 | somepage
| 1 | 1 | someotherpage
Now I need a query to return the following:
|PersonID | Count
------------------
|1 | 2
|2 | 0
------------------
Who can help me with this? I think its straight forward but I keep getting wrong values...
Thanks in advance!
SELECT p.ID AS PersonID,
COUNT(a.PersonID) AS `Count`
FROM Persons p
LEFT JOIN ActivePages a ON a.PersonID = p.ID
GROUP BY p.ID
select personid,count(personid) as count from activepages
right join Persons on ActivePages.PersonID = Persons.ID group by personid

Categories