I’m trying to gather “followers” for a specific user (#1 in this code).
I’m doing my primary select from followers
as the column following
will have user #1 and followers.userid will have the userid of the person doing the following.
Next I’m trying to get a count of records from the experiences
that have the user id of the follower (how many experiences does this follower have?)
Next, the follower will have rated each experience (1-5 stars) and I want to sum those ratings (experiences.stars) to get an average rating of all experiences.
Lastly, I want to join the followers user record from the users table.
I should end up with
userid, jobs, stars, * from users
SELECT * FROM followers AS F
RIGHT JOIN
(SELECT count(id) FROM experiences AS M WHERE M.userid = F.userid) AS jobs
RIGHT JOIN
(SELECT sum(stars) FROM experiences AS S WHERE S.userid = F.userid) AS stars
RIGHT JOIN
users AS U ON U.userid = F.userid
WHERE F.following = 1 /* #1 = the user # I want the follwers of/for */
I’ve also tried:
SELECT * FROM followers AS F,
(SELECT count(id) FROM experiences AS M WHERE M.userid = F.userid) AS jobs,
(SELECT sum(stars) FROM experiences AS S WHERE S.userid = F.userid) AS stars
RIGHT JOIN
users AS U ON U.userid = F.userid
WHERE F.following = 1 /* #1 = the user # I want the follwers of/for */
In cPanel, I’m getting an error that I have syntax error at WHERE F.userid in both statements.
A) what am I missing and B) is there a better way to do this?
2
Answers
It seems to me, the query would be easier to follow like so:
All those RIGHT JOINs you originally had would only give you followers that had both “types” of experiences.
Also, correlated subqueries can be expensive (and you didn’t need two of them…actually, you didn’t even need subqueries), so I’d also rework it like so….
Seems like there’s a couple of
ON
clauses missing.I know that
RIGHT
outer joins are supported, but why would we write it that way, and not write it asLEFT
outer joins. (We typically reserveRIGHT
joins to the towers of academia.)And it’s well past time to ditch the old-school comma syntax for join operations. (Yes, it’s still supported for backwards compatibility with existing statements. But new development should use the newer
JOIN
syntax.)The condition requiring a non-NULL value of
F.following
would effectively negate the “outerness” of the join, rendering it equivalent to an INNER join. For clarity, we should either write that as an inner JOIN, or if we want an outer join, we should relocate that condition to the appropriateON
clause.Also, best practice is to qualify all column references; even when they aren’t ambiguous to the optimizer, it makes it easier on the future reader (so the future reader doesn’t have to confirm which table contains the
id
column), as well as protecting the query from throwing “ambiguous column” errors in the future if a column namedid
is added to another table used by the query.Also, it’s not valid to reference columns from
F
in the outer query inside inline view queries. We can use a correlated subquery, but not as an inline view.The specification isn’t clear. Example data and sample of expected output would go a long ways to clarifying the requirements.
If we want to use correlated subqueries that return a single row, with a single column, we can put those in the SELECT list …
We could get an equivalent result using inline views, but that would look quite different.
I would tend to do the aggregation inside the inline view, something along the lines of this: