【问题标题】:Oracle Count even if nothing is thereOracle Count 即使什么都没有
【发布时间】:2011-11-27 22:27:05
【问题描述】:

所以我有这个查询:

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 个评论。

谢谢

【问题讨论】:

    标签: sql oracle count


    【解决方案1】:

    像这样使用 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;
    

    【讨论】:

    • 我喜欢您的简化解决方案。谢谢。
    【解决方案2】:

    您应该使用LEFT JOINS,而不是通过组合WHERE 子句中的结果来隐含INNER JOIN

    使用显式 JOIN

    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
    

    LEFT OUTER JOIN

    表 A 的左外连接(或简称为左连接)的结果和 B 总是包含“左”表 (A) 的所有记录,即使 join-condition 在“右”表中没有找到任何匹配的记录 (乙)。这意味着如果 ON 子句匹配 B 中的 0(零)条记录, 连接仍然会在结果中返回一行——但每个都为 NULL 来自 B 的列。

    【讨论】:

      猜你喜欢
      • 2018-07-18
      • 1970-01-01
      • 2020-03-19
      • 2015-07-31
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多