我正在尝试为特定用户收集“关注者”(此代码中为#1)。
我正在从followers
进行主要选择,因为列following
将拥有用户#1,并且followers.userid将拥有执行以下操作的人的用户ID。
接下来,我正在尝试从experiences
获取具有关注者用户ID的记录(此关注者有多少经历?)
接下来,关注者会评估每次体验(1-5星),我想总结这些评分(experiences.stars)以获得所有体验的平均评分。
最后,我想加入用户表中的关注者用户记录。
我应该结束 userid,jobs,stars,*来自用户
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 */
我也试过了:
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 */
在cPanel中,我收到一个错误,我在两个语句中的 WHERE F.userid 都有语法错误。
A)我缺少什么,B)有更好的方法吗?
答案 0 :(得分:1)
在我看来,查询会更容易理解:
SELECT *
FROM followers AS F
LEFT JOIN users AS U ON U.userid = F.userid
LEFT JOIN (SELECT count(id) FROM experiences AS M WHERE M.userid = **F.userid)** AS jobs
LEFT JOIN (SELECT sum(stars) FROM experiences AS S WHERE S.userid = F.userid) AS stars
WHERE F.following = 1 /* #1 = the user # I want the follwers of/for */
;
你原来拥有的所有正确的联接只会给你那些同时拥有"类型"经验。
此外,相关子查询可能很昂贵(而且你并不需要其中两个......实际上,你甚至不需要子查询),所以我也会这样重做。 ...
SELECT F.*, U.*, count(x.id), sum(x.stars)
FROM followers AS F
LEFT JOIN users AS U ON U.userid = F.userid
LEFT JOIN experiences AS x ON F.userid = x.user_id
WHERE F.following = 1
GROUP BY [all the fields selected in F and U, or just F.userid if server settings allow]
;
答案 1 :(得分:0)
似乎缺少一些ON
条款。
我知道支持RIGHT
外连接,但为什么我们这样编写它,而不是将它写为LEFT
外连接。 (我们通常会保留RIGHT
加入学术界的塔楼。)
现在很快就放弃了用于连接操作的旧式逗号语法。 (是的,它仍然支持向后兼容现有语句。但新开发应该使用较新的JOIN
语法。)
需要非NULL值F.following
的条件将有效地否定连接的“外部性”,使其等效于INNER连接。为清楚起见,我们应该将其写为内部JOIN,或者如果我们想要外连接,我们应该将该条件重新定位到适当的ON
子句。
此外,最佳做法是限定所有列引用;即使它们对优化器没有模糊性,它也会使未来的读者更容易(因此未来的读者不必确认哪个表包含id
列),以及保护查询不被丢弃如果将名为id
的列添加到查询使用的另一个表中,将来会出现“模糊列”错误。
此外,在内联视图查询中的外部查询中引用F
中的列无效。我们可以使用相关子查询,但不能使用内联视图。
规范不明确。示例数据和预期产出样本将大大有助于澄清要求。
如果我们想使用返回单行的相关子查询,只有一列,我们可以将它们放在SELECT列表中......
SELECT f.*
, u.*
, ( SELECT COUNT(m.id)
FROM experiences m
WHERE m.userid = f.userid
) AS jobs
, ( SELECT SUM(s.stars)
FROM experiences s
WHERE s.userid = f.userid
) AS stars
FROM followers f
LEFT
JOIN users u
ON u.userid = f.userid
WHERE f.following = 1 /* #1 = the user # I want the follwers of/for */
ORDER BY ...
我们可以使用内联视图获得相同的结果,但这看起来会有很大不同。
我倾向于在内联视图中进行聚合,类似于:
SELECT f.*
, u.*
, IFNULL(e.jobs,0) AS jobs
, IFNULL(e.stars,0) AS stars
FROM followers f
LEFT
JOIN users u
ON u.userid = f.userid
LEFT
JOIN ( SELECT ef.userid
, COUNT(ee.id) AS jobs
, SUM(ee.stars) AS stars
FROM followers ef
JOIN experiences ee
ON ee.userid = ef.userid
WHERE ef.following = 1 /* argument */
GROUP BY ef.userid
) e
ON e.userid = f.userid
WHERE f.following = 1 /* argument */
ORDER BY ...