Joins In MySQL for fetching multiple tables data - mysql

I have two table user and follow. I want to write view such that it will fetch all details of particular user along with that two extra column as follower count and followee count alias.
eg. user id=11 then all details from user tables plus followcount 1 and followed count1

SELECT u.id,
u.userid,
u.name,
u.mobile,
(SELECT Count(*)
FROM follow f
WHERE f.followerid = u.userid) AS follower,
(SELECT Count(*)
FROM follow f
WHERE f.followeeid = u.userid) AS followee
FROM users u

You can achieve this is by using JOIN statements in your query:
example of how you can achieve your final result:
CREATE VIEW [Followers] AS
SELECT a.name, a.email, a.mobile, COUNT(SELECT COUNT(followerID) FROM follow WHERE followerID = a.userid), COUNT(SELECT COUNT(followeeID) FROM follow WHERE followeeID = a.userid) FROM users a INNER JOIN follow b ON b.followerID = a.userid

Related

SQL intermediate table having column = max(column)

I have 2 tables: user and review, a one-to-many relationship.
When I execute the following query:
SELECT
user_id,
count(*) totalReviews,
USER . NAME
FROM
review,
USER
WHERE
USER .id = review.user_id
GROUP BY
user_id
I get:
1 2 marius
2 2 daniela
3 1 alin
What I want to do now is to display first 2 users because they have given the most reviews(2).
I tried adding having, if I hardcode having totalReviews=2 it works, but if I write having total = max(total) I get 0 results, while if I'm trying with,
SELECT
*
FROM
(
SELECT
user_id,
count(*) total,
USER . NAME
FROM
review,
USER
WHERE
USER .id = review.user_id
GROUP BY
user_id
) A
WHERE
total = (SELECT max(total) FROM A) `
I get an error (table A doesn't exist)
You would do this with ORDER BY and LIMIT:
SELECT u.id, count(*) as totalReviews, u.name
FROM review r JOIN
user u
ON u.id = r.user_id
GROUP BY u.id, u.name
ORDER BY totalReviews DESC
LIMIT 2;
Notes:
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
Table aliases make the query easier to write and read.
EDIT:
If occurs to me that you want all users with the maximum number of reviews, not exactly 2. Here is one method:
SELECT u.id, COUNT(*) as totalReviews, u.name
FROM review r JOIN
user u
ON u.id = r.user_id
GROUP BY u.id, u.name
HAVING totalReviews = (SELECT COUNT(*)
FROM review r2
GROUP BY r2.user_id
ORDER BY COUNT(*) DESC
LIMIT 1
);
Note that the subquery in the HAVING clause is simpler than the outer query. There is no need to bring in the user name.

MySQL Inline View "unknown fields"

I am presently in a DBS course and I am working on an inline view:
SELECT userId, firstname, lastname, gender
FROM
(SELECT COUNT(dvdId) dvdId, u.userId
FROM userDVD
JOIN users u ON userDVD.userId = u.userId
GROUP BY userId) as T
WHERE gender = 'F';
When I run the Query it returns the error unknown column in field list. If I try to specify
u.firstname, u.lastname, u.gender
I return the same error. Any thoughts?
SELECT T.userId, T.firstname, T.lastname, T.gender
FROM (
SELECT users.userId, users.firstname, users.lastname, users.gender
FROM userDVD
JOIN users ON userDVD.userId = users.userId
WHERE gender = 'F' GROUP BY userId
) as T;
I worked through it and it turns out I didn't realize that because I had to alias my inline view that I needed to specify it in the original select statement. This concept was sadly not covered in my course. I appreciate those who gave helpful tips versus rude comments. So, Thank you Drew and Matt
Drew is right that you have a derived table T, but I'll attempt to add some details which might be useful to you as you are in a course.
you have a derived table T
an outer query (first select)
an inner query (second select in brackets)
the inner query uses a table alias of u for users.
the final columns of the inner query are dvdId which is a count of the dvdIds in userDvd table and userId
Because an outer query is constrained to use the final recordset of the inner query only those 2 columns are available to be selected and seeing they don't include firstname, lastname, or gender you are recieving the error.
If you want to keep your query the same but to use those columns you could join your derived table back to the user table and get the columns you desire. Such as this:
SELECT userId, firstname, lastname, gender
FROM
(SELECT COUNT(dvdId) dvdId, u.userId
FROM userDVD
JOIN users u ON userDVD.userId = u.userId
GROUP BY userId) as T
INNER JOIN users u2
ON t.user_id = u2.user_id
WHERE gender = 'F';
That technique to join back to the original table is great for when you have to optimize an aggregation that is on a large table or look for duplicates or something like that. However in your case you really just need a single query aggregating on all of the columns you want in the result set such as this:
SELECT
u.userId, u.firstname, u.lastname, u.gender, COUNT(d.dvdId) as DVDCount
FROM
userDVD d
JOIN users u
ON d.userId = u.userId
WHERE u.gender = 'F'
GROUP BY
u.userId, u.firstname, u.lastname, u.gender
;

Join 3 tables to get single row

I'm trying to join multiple table to get single row result for each id. This result will be send to angular UI
I have 3 tables user, friends and trip
A user can have multiple friends but one trip
I like to get all details corresponding to a user in one row, probably friends as field like an array?
This is how my table looks.
http://sqlfiddle.com/#!9/0879d/2
https://gist.github.com/tomalex0/9dee4fff85583732e7d0
group_concat should do the trick for you:
SELECT u.*, t.*, friendlist
FROM user u
LEFT JOIN trip t ON u.id = t.user_id
LEFT JOIN (SELECT user_id, GROUP_CONCAT(CONCAT (name, '- ', email)) friendlist
FROM friends
GROUP BY user_id) f ON f.user_id = u.id

Select count from sub table

I need to get the count from one of the sub tables / joined tables involved in the query. I will demonstrate with a simple example:
Table: user
id name etc
-------------------------------------------
1 u1
2 u2
Table: exercise
id userId etc
-------------------------------------------
1 1
2 1
Now I need to select from user table various fields like id, name, etc along with the count of various user id in exercise table.
For example, in the above case I need the output:
id name count
-------------------------------------------
1 u1 2 --since two u1's are present in exercise
2 u2 0 --since no u2's are present in exercise
I tried this: but I get syntax error:
--actual query is very complex
SELECT u.id, u.name, COUNT(e.*)
FROM user AS u
JOIN exercise AS e ON u.id = e.userId
I tried this: but I get syntax error again:
--actual query is very complex
SELECT u.id, u.name, (SELECT COUNT(*) FROM e)
FROM user AS u
JOIN exercise AS e ON u.id = e.userId
This works, as a sub query, but is painfully slow (5 to 13 seconds for about 10000 rows in each table):
--actual query is very complex
SELECT u.id, u.name, (SELECT COUNT(*) FROM exercise WHERE e.userId = u.id)
FROM user AS u
Is there a way I can get the count info in one single query, with the help of join or so? Sub query is very slow for my needs.
Try using a GROUP BY, like this:
SELECT u.id, u.name, COUNT(e.userId)
FROM user AS u
LEFT JOIN exercise AS e
ON u.id = e.userId
GROUP BY u.id
Try this:
SELECT u.id, u.name, COUNT(e.userId)
FROM user AS u
LEFT JOIN exercise AS e
ON u.id = e.userId
GROUP BY u.id,u.name
Left join will still return you row from user table even if there are no records in exercise table.

MYSQL JOIN syntax How to Join Three Tables

The following query does what I want. It returns all the resuls in the users table and then if there is a match in the details tble, returns the relevant data
users
id|username
details
id|userid|firstname|lastname
$sql = "SELECT u.*, d.*
FROM `users` u
LEFT JOIN `details` d on
u.id = d.userid
ORDER BY $strorder";
However, when I try to join an additonal table where I want to do the same thing--return all the results of the users table and if there is a match in the third table, return the relevant data (total followers of this user)--it only returns one record.
3rd table
follow
id|followerid|followedid
$sql = "SELECT u.*, d.*, COUNT(f.id)
FROM `users` u
LEFT JOIN `details` d on
u.id = d.userid
LEFT JOIN `follow` f on
u.id = f.followedid
ORDER BY $strorder";
Can anyone see what I am doing wrong? Thanks in advance for any suggestions.
Many thanks.
Try to avoid * to select fields, it will be clearer to group your datas (even if mysql is quite permissive with groupings).
When you have an aggregate function (like COUNT, SUM), the other "non aggregated" requested fields should be in a GROUP BY clause.
Mysql don't force you to GROUP BY all the fields, but... I think it's quite a good habit to be "as ANSI as possible" (usefull when you use another DBMS)
SELECT u.id, u.username, d.firstname, d.lastname, count(*) as numberfollowers
FROM user u
LEFT JOIN details d on u.id = d.userid
LEFT JOIN follow f on u.id = f.followedid
GROUP BY u.id, u.username, d.firstname, d.lastname --or just GROUP BY u.id with Mysql
ORDER BY count(*) desc
COUNT being an aggregate function, when selected with other columns, requires you to group your results by those other columns in the select list.
You should rewrite your query with columns that you want to select from users and details and group by those columns.