how to join 3 tables, topic, comment and user - mysql

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

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.

How to join a table to itself and get max row then connect another table to it

I have a table that contains redundant entries. What i need is to
get the column with max id data, then connect the table to users table and get name based on the max row user_id
tracking table
id | labref | user_id
-----------------------
1 | a | 1
------------------------
2 | a | 3
------------------------
3 | b | 4
------------------------
5 | b | 7
------------------------
SQL Query:
SELECT id,labref,user_id FROM tracking_table t WHERE t.id =
(SELECT MAX(t2.id) FROM tracking_table t2, user u WHERE t.labref = t2.labref AND u.id = t2.user_id)
Result:
id | labref | user_id
--------------------
2 | a | 3
--------------------
5 | b | 7
--------------------
Would like to join users table below
Users Table
id | name
-------------
1 | ua
------------
2 | ub
------------
3 | uc
------------
4 | ud
------------
5 | ue
-------------
7 | uf
-------------
Desired results should be as follows:
id | labref | name
--------------------
2 | a | uc
--------------------
5 | b | uf
--------------------
Suggestions as to where I am now stuck?
You can use a subquery to find the maximum id value for each lab reference. Then, join to this subquery to leave you with the effective rows you want. Finally, join this to the user table to bring in the usernames.
SELECT
t1.id,
t1.labref,
u.name
FROM tracking_table t1
INNER JOIN
(
SELECT labref, MAX(id) AS max_id
FROM tracking_table
GROUP BY labref
) t2
ON t1.labref = t2.labref AND
t1.id = t2.max_id
INNER JOIN user_table u
ON t1.user_id = u.id
Output:
Demo here:
Rextester
Please check this statement. Does it fit your needs?
SELECT t.id, t.labref, u.name
FROM tracking_table t
INNER JOIN users u
on t.user_id = u.id
WHERE t.id =
(SELECT MAX(t2.id)
FROM tracking_table t2, user u
WHERE t.labref = t2.labref AND u.id = t2.user_id)
The users table is unnecessary in the subquery. You need it in the main query:
SELECT t.id, t.labref, u.name
FROM tracking_table t
JOIN user u ON u.id = t.user_id
WHERE t.id = (SELECT MAX(t2.id) FROM tracking_table t2 WHERE t.labref = t2.labref);
You shouldn't use comma-separated joins anymore by the way. They were made redundant in 1992. Use explicit ANSI joins instead.

MySQL syntax issue, multiple SELECT statements

I am working of a project that has 2 tables as follows: users_fb and posts
I spent 3 hours playing with the code and then I gave up.
table: posts
+-----+---------+---------+---------+---------+-----------+
| id | by_user | by_page | votes | status | time |
+-----+---------+---------+---------+---------+-----------+
| 1 | 1 | 0 | 20 | 1 | 372041014 |
+-----+---------+---------+---------+---------+-----------+
table: users_fb
+-----+-----------+-------+---------+--------+-------+
| id | username | name | gender | fb_id | email |
+-----+-----------+-------+---------+--------+-------+
SELECT username,
(
SELECT COUNT(b.by_user)
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.username
) AS totalCount ,
(
SELECT IFNULL(SUM(b.votes),0)
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
GROUP BY users_fb.id
) AS total_votes
FROM users_fb ORDER BY total_votes DESC
The desired output
+-------------------+-------------+-------------+
| username | totalCount | total_votes |
+-------------------+-------------+-------------+
| user4 | 1 | 25 |
| user1 | 0 | 0 |
| user2 | 0 | 0 |
| user3 | 0 | 0 |
+-------------------+-------------+-------------+
UNFORTUNATELY: This is what I am getting
+-------------------+-------------+-------------+
| username | totalCount | total_votes |
+-------------------+-------------+-------------+
| user4 | 1 | 25 |
| user1 | 1 | 25 |
| user2 | 1 | 25 |
| user3 | 1 | 25 |
+-------------------+-------------+-------------+
If you need any further information, let me know. Thanks for your help.
You don't appear to have anything to join your tables together to match up with posts / votes go with which user.
Something like this should do it
SELECT users_fb.username, Sub1.postcount, Sub2.votecount
FROM users_fb
LEFT OUTER JOIN(
SELECT a.username, COUNT(*) AS postcount
FROM users_fb a
INNER JOIN posts b
ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.username
) Sub1
ON users_fb.username = Sub1.username
LEFT OUTER JOIN(
SELECT users_fb.id, IFNULL(SUM(b.votes),0) AS votecount
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user
GROUP BY users_fb.id
) Sub2
ON users_fb.id = Sub2.id
Possibly simplified to
SELECT a.username, SUM(IF(b.by_page = '0', 1, 0)) AS postcount, IFNULL(SUM(b.votes),0) AS votecount
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user
GROUP BY a.username
Since you are doing no matching of the selects (i.e. there is no binding WHERE between them), MySQL has no wait to make them show together.
You should do something like this:
SELECT username, totalCount.count, total_votesGROUPED.sum
FROM users_fb
LEFT JOIN (
SELECT COUNT(b.by_user) as count, a.username
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.username
) AS totalCount ON totalCount.username = users_fb.username,
(
SELECT IFNULL(SUM(b.votes),0) as sum, id
FROM users_fb a LEFT JOIN posts b ON a.id = b.by_user
GROUP BY users_fb.id
) AS total_votesGROUPED ON total_votesGROUPED.id = users_fb.id
ORDER BY total_votes DESC
If I had a bit more information, I could test it
Quite a few problems, the biggest is that you don't make any join between your "main query" and your "subqueries".
So finally, something like that should be better.
SELECT
a.username,
SUM (CASE WHEN b.by_page IS NOT NULL and b.by_page = '0' then 1 else 0 end) as cnt,
SUM (IFNULL(b.votes),0) as nbVotes,
FROM users_fb a
LEFT JOIN posts b ON a.id = b.by_user
GROUP BY users_fb.id
SELECT a.username,
COUNT(b.by_user) totalCount,
SUM(IFNULL(b.votes,0)) total_votes
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user
WHERE b.by_page = '0'
GROUP BY a.id,a.username
SELECT username, IFNULL(COUNT(b.by_user), 0) totalCount, IFNULL(SUM(c.votes), 0) total_votes
FROM users_fb a
LEFT JOIN posts b
ON a.id = b.by_user AND b.by_page = 0
LEFT JOIN posts c
ON a.id = b.by_user
GROUP BY username
SQLFIDDLE

mysql query to count

i am doing sql query to get values from db, db structure as follows...
fcats
| id | title | section |
+----+--------+---------+
| 1 | test | gd |
+----+--------+---------+
ftopics
| id | title | cat_id |
+----+--------+---------+
| 1 | test1 | 1 |
+----+--------+---------+
fposts
| id | post | topic_id |
+----+-------+----------+
| 1 | post | 1 |
+----+-------+----------+
I want to get total number of topics and posts for given category and using following query...
SELECT id, title (SELECT count(id) FROM ftopics WHERE cat_id = id) AS total_topics FROM fcats WHERE section = "gd"
and it gives correct results for total topics but how can i get total number of posts for all categories, i am abit confused about, please help me to write this query. thanks.
try this:
SELECT
t.id,
t.title,
COUNT(f.id) + COUNT(p.id) AS total
FROM fcats t
LEFT OUTER JOIN ftopics f
ON f.cat_id = t.id
LEFT OUTER JOIN fposts p
ON p.cat_id = t.id
WHERE t.section = "gd"
GROUP BY t.id, t.title
SELECT
t.id,
t.title,
COUNT(f.id) AS total_topics,
(SELECT COUNT(p.id) FROM fposts WHERE topic_id = t.id) total_posts
FROM fcats t
INNER JOIN ftopics f
ON f.cat_id = t.id
WHERE t.section = "gd"
GROUP BY t.id, t.title
not sure if this is the right syntax, updated the other answers code to try to answer your request for the two totals.

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