SELECT,2表从第2表开始,RIGHT JOIN在3表

时间:2018-04-10 20:43:10

标签: mysql count right-join

我正在尝试为特定用户收集“关注者”(此代码中为#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)有更好的方法吗?

2 个答案:

答案 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 ...