MySQL Left Join add doesn't exists rows to result - mysql

I have this two tables:
Users
uID | NAME |
1 | N1 |
2 | N2 |
raports
rID| TEXT | DATE | USER
1 | awda | 2015-02-16 | 1
And I try to get all users with raports.DATE = 2015-02-16 or users for which raport with this date doesn't exist.
I try something like this:
SELECT * FROM `users` LEFT JOIN `raports` ON uid = user WHERE (usr_id in ('1', '2'))

Getting all users with report date could be done as
select
u.*
from users u
join raports r on r.user = u.uID
where r.date = '2015-02-16'
Getting users who are not in that report date could be done as
select
u.* from users u
left join raports r on r.user = u.uID and r.date = '2015-02-16'
where r.rID is null

Related

Many to Many relationships with an initial pivot condition

I have three tables groups, users and group_user.
While groups and users have an id and name column, the bellow is
the group_user table
+----+----------+---------+
| id | group_id | user_id |
+----+----------+---------+
| 12 | 5 | 1 |
| 13 | 5 | 8 |
| 14 | 5 | 7 |
+----+----------+---------+
The issue am facing is, I have a user with id 7, and am trying
to get the group of this user (which is 5 from above schema diagram), then retrieve every other user
in that group (user with id 1 and 8).
I tried doing something like this:
select `groups`.id, `groups`.name, users.id, users.name from `groups`
left join group_user on `groups`.id = group_user.group_id and group_user.user_id = 7
left join users on group_user.user_id = users.id
And expectedly the result is not accurate
Please try following query:
select g.name group_name, u.name user_name from group_user gu
left join users u on u.id = gu.user_id
left join groups g on g.id = gu.group_id
where gu.group_id in (select group_id from group_user where user_id = 7)
You must join users to 2 copies of group_user and finally groups with INNER joins:
select gu2.group_id, g.name group_name, u.id user_id, u.name user_name
from `users` u
inner join group_user gu on gu.user_id = u.id
inner join group_user gu2 on gu2.group_id = gu.group_id and gu2.user_id = 7
inner join `groups` g on g.id = gu2.group_id
See a simplified demo.

Joining Max Row where Col

I have this query:
SELECT
`shift`.`uid`,
`shift`.`activity`,
`users`.`fname`,
`users`.`lname`
FROM `shift`, `users`
WHERE `shift`.`uid` = `users`.`id`
It works fine just like that, but I need to add a new column from another table and order by it.
times :
| uid | User | time |
+++++++++++++++++++++
| 3 | bob | 1231 |
| 3 | bob | 1291 |
| 4 | ned | 1651 |
| 5 | ted | 5679 |
| 6 | joe | 7665 |
| 6 | joe | 7864 |
How can I include the maximum time from the time table for each user (WHERE times.uid = shift.uid) and then order by that column?
Trouble is, all the other tables have one row per user but the time table has multiple and I can't figure out the correct combination of joins and group by.
You could join on an aggregate query:
SELECT `shift`.`uid`,
`shift`.`activity`,
`users`.`fname`,
`users`.`lname` ,
t.max_time
FROM `shift`
JOIN `users` ON `shift`.`uid` = `users`.`id`
JOIN (SELECT `uid`, MAX(`time`) AS max_time
FROM `times`
GROUP BY `uid`) t ON shift.uid = t.uid
ORDER BY t.max_time
A pretty simple way to approach this is using a correlated subquery:
SELECT s.`uid`, s.`activity`, u.`fname`, u.`lname`,
(SELECT MAX(tt.time)
FROM timetable tt
WHERE tt.uid = u.id
) as maxtime
FROM `shift` s JOIN
`users` u
ON s.`uid` = u.`id`;
The advantage of this approach is performance. With an index on timetable(uid, time), this should work better than doing an aggregation at the outer level (because the query will take advantage of the index).
SELECT s.uid,
s.activity,
u.fname,
u.lname,
MAX(t.time) as maxtime
FROM shift s,
INNER JOIN users u ON u.id = s.uid
INNER JOIN times t ON t.uid = u.id
GROUP BY s.uid,
s.activity,
u.fname,
u.lname
ORDER BY maxtime

how to join 3 tables, topic, comment and user

I have 3 tables, tbl_topic, tbl_comment, tbl_user.
I want to select all the topics created by the user and also the topics that he commented on even if he is not the creator. Here is my database:
tbl_topic
----------
topic_id
topic_title
user_id
tbl_comment
----------
comment_id
comment_message
user_id
topic_id
tbl_user
----------
user_id
user_name
Need it so badly. Thanks!
So far i got this
select * from tbl_topic T inner join tbl_comment C on T.topic_id = C.topic_id inner join tbl_user U on T.user_id = U.user_id GROUP BY T.topic_id
My problem is it only returns the topics that has comments on it. I want to include the topics created by the user even if it has 0 comments.
I want the result to be like this:
+-----------+-----------+----------+-------------+----------------+----------+-------
| topic_id | topic_title | user_id | comment_id | comment_message | user_id | topic_id |
+-----------+-----------+----------+-------------+----------------+----------+--------
| 1 | my topic | 1 | 1 | comment me | 1 | 1
| 2 | others | 2 | 2 | comment me | 1 | 2
| 3 | my nocoment| 1 | NULL | NULL | NULL | NULL
+-----------+---------+--------+-------------+----------+----------+---------+--------
----------+-----------+
user_id | user_name |
-----------+-----------
1 | me |
2 | someone |
1 | me
-----------+---------+--
I messed up with my fields in my tables, the user_id beside comment_message should be comment_user_id but i already created my database that way. Can you help make this possible?
The query below uses UNION in the subquery. The first SELECT gets all topics created by user. The second SELECT statement gets all comments of the user and joins it to table tbl_topic so we can get the topic_title.
SELECT topic_ID, topic_title
FROM
(
SELECT a.user_ID, b.topic_ID, b.topic_title
FROM tbl_user a
INNER JOIN tbl_topic b
ON a.user_ID = b.user_ID
UNION
SELECT a.user_ID, c.topic_ID, c.topic_title
FROM tbl_user a
INNER JOIN tbl_comment b
ON a.user_ID = b.user_ID
INNER JOIN tbl_topic c
ON b.topic_ID = c.topic_ID
) x
WHERE x.user_ID = ?
Try the query below. This will show all the fields.
SELECT tt.*, tc.*, tbl_user.*
FROM tbl_topic AS tt INNER JOIN tbl_comment AS tc ON tt.topic_id = tc.topic_id INNER JOIN tbl_user as tc ON tc.user_id = tu.user_id;
WHERE tu.user_id = x
If you have to filter add to the WHERE clause to the query.
Go with a left join. But there is still a Problem left, you will only get ONE table-comment and ONE user. To get more, you can use the GROUP_CONCAT function, like here: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
select * from tbl_topic T
LEFT JOIN tbl_comment C on T.topic_id = C.topic_id
LEFT join tbl_user U on T.user_id = U.user_id
WHERE T.user_id = x
GROUP BY T.topic_id
EDIT: the where clause was missing

Trouble with join statement for selecting data across tables with MYSQL

I'm trying to display events that a user has created and events that he has signed up for. I have three tables for this.
//events
| event_id | event_title | event_details | event_timestamp | userid
1 title1 test 1234 1
2 title2 testing2 123 2
//registration_items : event_id references events.event_id
| id | event_id | task_name
1 2 task 1
//registration_signup : id references registration_items.id
| id | userid | timestamp
1 1 1234
Here's the current query I have. Right now it only displays the event the user created. It should display both created events and ones he signed up for
select events.*, registration_items.*, registration_signup.*, users.username from events
INNER JOIN users on users.userid = events.userid
LEFT JOIN registration_items ON registration_items.event_id = events.event_id
LEFT JOIN registration_signup ON registration_signup.id = registration_items.id
WHERE events.userid = '$user_id' OR registration_signup.userid = '$user_id' ORDER BY events.event_timestamp DESC
For userid1 the output should be
Title
title1 (the user created this)
title2 (the user signed up for this)
For userid2 the output should be
Title
title2
select events.*, registration_items.*, registration_signup.*, users.username
from events
INNER JOIN users on users.userid = events.userid
LEFT JOIN registration_items ON registration_items.event_id = events.event_id
LEFT JOIN registration_signup ON registration_signup.id = registration_items.id
WHERE registration_signup.userid = '$user_id'
union
select events.*, registration_items.*, registration_signup.*, users.username
from events
INNER JOIN users on users.userid = events.userid
INNER JOIN registration_items ON registration_items.event_id = events.event_id
INNER JOIN registration_signup ON registration_signup.id = registration_items.id
WHERE events.userid = '$user_id'
ORDER BY events.event_timestamp DESC
I am not sure if it's correct to guess that you have a typo in the sample data. Because your query works the moment you change the user id to 1 for both events, signed up events.. So please take a look at this reference demo and comment if it's not a typo...
SQLFIDDLE DEMO
query: (your query..)
select u.userid,e.event_id as id,
ri.event_id as evt, e.event_title,
ri.task_name,
rs.timestamp,
u.name from events e
INNER JOIN users u on
u.userid = e.userid
LEFT JOIN registration_items ri ON
ri.event_id = e.event_id
LEFT JOIN registration_signup rs ON
rs.id = ri.id
WHERE e.userid = '1' or
rs.userid = '1'
ORDER BY e.event_timestamp DESC
;
Results:
| USERID | ID | EVT | EVENT_TITLE | TASK_NAME | TIMESTAMP | NAME |
------------------------------------------------------------------
| 1 | 1 | 1 | title1 | task 1 | 1234 | john |
| 1 | 2 | 2 | title2 | task 1.2 | 3456 | john |

LEFT JOIN 3 columns to get username

I have three columns I need to join which comes from 3 different tables,
Contributions table:
+-----------+---------------------+
| record_id | contributor_user_id |
+-----------+---------------------+
| 1 | 2 |
+-----------+---------------------+
| 1 | 5 |
+-----------+---------------------+
Members table:
+--------------+---------+
| username | user_id |
+--------------+---------+
| Test | 1 |
+--------------+---------+
| Test2 | 5 |
+--------------+---------+
| Test3 | 6 |
+--------------+---------+
Records table:
+---------+-----------+
| user_id | record_id |
+---------+-----------+
| 28 | 1 |
+---------+-----------+
For what I need to return is the username and user_id for displaying the record owner. Also, display the username and the user_id, but this can be multiple (more than 1+ user). I've tried this:
SELECT usr.username,
usr.user_id,
rec.record_id,
contrib.record_id,
contrib.contributor_user_id
FROM
(
records rec
INNER JOIN members usr ON rec.user_id = usr.user_id
# this returns records as NULL
LEFT OUTER JOIN contributions contrib ON rec.record_id = contrib.record_id AND contrib.contributor_user_id = usr.user_id
# this works, but I need the username to be displayed too
LEFT OUTER JOIN contributions contrib ON rec.record_id = contrib.record_id
)
WHERE rec.record_id = 1
Try nesting the join for contributing users inside of the left join to contributions.
SELECT u.username, u.user_id, r.record_id, u2.username as ContributorName, u2.user_id as ContributorId
FROM records r
INNER JOIN members u
ON r.user_id = u.user_id
LEFT JOIN contributions c
INNER JOIN members u2
ON c.contributor_user_id = u2.user_id
ON r.record_id = c.record_id
WHERE r.record_id = 1
SELECT
usr.username AS record_owner
, usr.user_id AS record_owner_id
, rec.record_id
, con.contributor_user_id AS contributor_id
, contributors.username AS contributor_name
FROM
records rec
INNER JOIN
members usr
ON rec.user_id = usr.user_id
LEFT OUTER JOIN
contributions con
ON rec.record_id = con.record_id
INNER JOIN
members contributors
ON con.contributor_user_id = contributors.user_id
WHERE
rec.record_id = 1