SELECT,从第 2 次算起 2 table,第 3 次 RIGHT JOIN
SELECT, 2 counts from 2nd table, RIGHT JOIN on 3rd
我正在尝试为特定用户收集 "followers"(此代码中的#1)。
我正在从 followers
做我的主要 select 因为列 following
将有用户 #1 而 followers.userid 将有执行此操作的人的用户 ID正在关注。
接下来,我尝试从 experiences
中获取具有关注者用户 ID 的记录数(该关注者有多少次体验?)
接下来,关注者将对每个体验进行评分(1-5 星),我想将这些评分相加 (experiences.stars) 以获得所有体验的平均评分。
最后,我想加入来自用户table的followers用户记录。
我应该以
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) 有更好的方法吗?
在我看来,这样的查询会更容易理解:
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 */
;
您最初拥有的所有那些 RIGHT JOIN 只会给您拥有两种 "types" 经验的追随者。
此外,相关子查询可能很昂贵(而且您不需要其中两个......实际上,您甚至不需要子查询),所以我也会像这样重新处理它....
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]
;
似乎缺少几个 ON
子句。
我知道支持RIGHT
外连接,但为什么要这样写,而不是写成LEFT
外连接。 (我们通常保留 RIGHT
加入学术界的塔楼。)
而且,放弃连接操作的 old-school 逗号语法已经过去了。 (是的,它仍然支持与现有语句的向后兼容性。但是新开发应该使用更新的 JOIN
语法。)
要求 F.following
的 non-NULL 值的条件将有效地否定联接的 "outerness",使其等同于 INNER 联接。为了清楚起见,我们应该将其写为内部 JOIN,或者如果我们想要外部联接,我们应该将该条件重新定位到适当的 ON
子句。
此外,最佳做法是限定 所有 列引用;即使它们对优化器没有歧义,它也会使未来 reader 变得更容易(因此未来 reader 不必确认哪个 table 包含 id
列),以及如果将名为 id
的列添加到查询使用的另一个 table 列,则保护查询将来不会抛出 "ambiguous column" 错误。
此外,在内联视图查询中的外部查询中引用来自 F
的列是无效的。我们可以使用相关子查询,但不能作为内联视图。
规格不明确。示例数据和预期输出示例将大大有助于阐明需求。
如果我们想使用 return 单行单列的相关子查询,我们可以将它们放在 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 ...
我正在尝试为特定用户收集 "followers"(此代码中的#1)。
我正在从 followers
做我的主要 select 因为列 following
将有用户 #1 而 followers.userid 将有执行此操作的人的用户 ID正在关注。
接下来,我尝试从 experiences
中获取具有关注者用户 ID 的记录数(该关注者有多少次体验?)
接下来,关注者将对每个体验进行评分(1-5 星),我想将这些评分相加 (experiences.stars) 以获得所有体验的平均评分。
最后,我想加入来自用户table的followers用户记录。
我应该以 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) 有更好的方法吗?
在我看来,这样的查询会更容易理解:
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 */
;
您最初拥有的所有那些 RIGHT JOIN 只会给您拥有两种 "types" 经验的追随者。
此外,相关子查询可能很昂贵(而且您不需要其中两个......实际上,您甚至不需要子查询),所以我也会像这样重新处理它....
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]
;
似乎缺少几个 ON
子句。
我知道支持RIGHT
外连接,但为什么要这样写,而不是写成LEFT
外连接。 (我们通常保留 RIGHT
加入学术界的塔楼。)
而且,放弃连接操作的 old-school 逗号语法已经过去了。 (是的,它仍然支持与现有语句的向后兼容性。但是新开发应该使用更新的 JOIN
语法。)
要求 F.following
的 non-NULL 值的条件将有效地否定联接的 "outerness",使其等同于 INNER 联接。为了清楚起见,我们应该将其写为内部 JOIN,或者如果我们想要外部联接,我们应该将该条件重新定位到适当的 ON
子句。
此外,最佳做法是限定 所有 列引用;即使它们对优化器没有歧义,它也会使未来 reader 变得更容易(因此未来 reader 不必确认哪个 table 包含 id
列),以及如果将名为 id
的列添加到查询使用的另一个 table 列,则保护查询将来不会抛出 "ambiguous column" 错误。
此外,在内联视图查询中的外部查询中引用来自 F
的列是无效的。我们可以使用相关子查询,但不能作为内联视图。
规格不明确。示例数据和预期输出示例将大大有助于阐明需求。
如果我们想使用 return 单行单列的相关子查询,我们可以将它们放在 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 ...