所以我有这个问题:
SELECT p.*, d.reviews, TRUNC(ds.ratingAvg, 2) as ratingAvg
FROM place p,
(SELECT pid,
COUNT(rating) as ratings,
COUNT(review) as reviews
FROM describes
GROUP BY pid) d,
(SELECT pid, AVG(rating) as ratingAvg FROM describes GROUP BY pid) ds
WHERE d.pid = p.pid AND d.pid = ds.pid
;
它将从地方返回东西,然后d是另一个表描述。它将获得该地点的评论数量和平均评分。只要描述表中有某些内容,这就完美无缺。我怎样才能获得没有任何内容的东西。基本上是0评级或0评论。
由于
答案 0 :(得分:2)
使用coalesce()和LEFT JOIN,如下所示:
SELECT p.*
,COALESCE(d.reviews, 0) AS reviews
,COALESCE(ds.ratingAvg, 0) AS ratingAvg
FROM place p
LEFT JOIN (
SELECT pid
-- ,COUNT(rating) AS ratings -- unused?
,COUNT(review) AS reviews
FROM describes
GROUP BY pid) d ON d.pid = p.pid
LEFT JOIN (
SELECT pid
,TRUNC(AVG(rating), 2) AS ratingAvg
FROM describes
GROUP BY pid) ds ON ds.pid = p.pid;
注意我如何在第二个JOIN中使用ON ds.pid = p.pid
,而不是像ON ds.pid = d.pid
那样使用SELECT p.*
,COALESCE(d.reviews, 0) AS reviews
,COALESCE(d.ratingAvg, 0) AS ratingAvg
FROM place p
LEFT JOIN (
SELECT pid
-- ,COUNT(rating) AS ratings -- unused?
,COUNT(review) AS reviews
,TRUNC(AVG(rating), 2) AS ratingAvg
FROM describes
GROUP BY pid) d ON d.pid = p.pid;
。
如果第三个关系保持连接到第二个关系,而第二个关系又连接到第一个关系,则如果在第二个关系中找不到任何行,则会丢失第三个关系中的行。如果可能,左连接应该是第一个关系。在这种特殊情况下没有任何区别,因为我们在同一个表上有两个无条件查询 - 应该简化:
{{1}}
答案 1 :(得分:2)
通过合并INNER JOIN
子句中的结果而不是隐式WHERE
,您应该使用LEFT JOINS
。
SELECT p.*
, d.reviews
, TRUNC(ds.ratingAvg, 2) as ratingAvg
FROM place p
LEFT JOIN (
SELECT pid
, COUNT(rating) as ratings
, COUNT(review) as reviews
FROM describes
GROUP BY
pid
) d ON d.pid = p.pid
LEFT JOIN (
SELECT pid
, AVG(rating) as ratingAvg
FROM describes
GROUP BY
pid
) ds ON ds.pid = d.pid
表A和表的左外连接(或简称左连接)的结果 B总是包含“左”表(A)的所有记录,即使是 join-condition在“右”表中找不到任何匹配的记录 (B)。这意味着如果ON子句匹配B中的0(零)记录, 连接仍会在结果中返回一行 - 但每个中都有NULL B栏。