【问题标题】:is there a way of joining two tables with the clause, "inner join," then followed by multiple "left join" clause有没有办法用“内连接”子句连接两个表,然后是多个“左连接”子句
【发布时间】:2019-11-08 15:22:46
【问题描述】:

我正在针对四个表设置mysql查询,我希望左边的结果不会影响内连接的查询。我做错了什么?原谅我的天真

这里的问题是,当我删除查询中的两个左连接时,我得到了预期的八个结果,但是在查询中使用左连接时,即使产品表中有更多产品,我也只能得到一个结果。

$this->getAllRecords("SELECT t.content_type_name as type, 
                        p.title,p.start_date, p.end_date, p.last_enroll_date, 
                        p.seat, p.cost, p.description, COUNT(r.stars) as review_count, 
                        AVG(r.stars) as stars, i.image, p.location 
                    FROM content_type t 
                        INNER JOIN product p ON t.content_type_id=c.content_type_id 
                        LEFT JOIN product_review r ON p.product_id=r.product_id 
                        LEFT JOIN image i ON p.uid=i.reference_page_or_product 
                            AND p.active=1 
                    ORDER BY RAND() 
                    LIMIT 8"))

我想要所有产品,无论是否有评论和图片

【问题讨论】:

  • 您是否直接对数据库运行完整查询以确认您的代码中的某些内容没有过滤掉所需的行?
  • 看起来很奇怪,左连接你得到更少的行......显示没有左连接的代码......
  • 能否请你给我们看一个这个问题的例子,你可以在这里看到dbfiddle.uk/…这通常不是问题
  • 很抱歉来晚了。 @Patrick Q 我已经对数据库运行了查询,但我不知道是什么过滤了结果。就像我之前提到的,一旦我取消了两个左连接子句,查询就会正常工作。
  • @scaisEdge 这里是没有左连接的代码,它按预期工作``` $this->getAllRecords("SELECT t.content_type_name as type, p.title, p.start_date, p. end_date, p.last_enroll_date, p.seat, p.cost, p.description, p.location FROM content_type t INNER JOIN product p ON t.content_type_id=c.content_type_id AND p.active=1 ORDER BY RAND() LIMIT 8" ))```

标签: php mysql


【解决方案1】:

您正在使用没有 group by 的聚合函数,这可能会产生不可预知的结果(可能您使用的是 5.7 之前的 mysql db 版本)

聚合结果可能与空值有关,这也可以减少/省略结果

您应该使用 group by 进行聚合功能并使用子查询来获取相关的有效结果..并使用 subqiery 进行左连接

SELECT t.content_type_name as type
      , p.title,p.start_date
      , p.end_date
      , p.last_enroll_date
      , p.seat
      , p.cost
      , p.description
      , p.location 
      , i.image
      , t.review_count
      , t.stars
FROM content_type t 
INNER JOIN product p ON t.content_type_id=c.content_type_id 
    AND p.active=1 
LEFT JOIN  (
  SELECT r.product_id
          , COUNT(r.stars) as review_count
          , AVG(r.stars) as stars
  FROM product_review r
  GROUP BY r.product_id
) t ON ON p.product_id=t.product_id 
LEFT JOIN image i ON p.uid=i.reference_page_or_product 
ORDER BY RAND() 
LIMIT 8

为了更好地查看 p.active=1 应该分配给产品的 on 子句

【讨论】:

    【解决方案2】:

    请参阅此页面以了解正确的连接嵌套和对括号的使用:https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html

    但是SQL有个bug,应该写成WHERE:

    SELECT t.content_type_name as type, p.title,p.start_date, p.end_date, p.last_enroll_date, 
            p.seat, p.cost, p.description, COUNT(r.stars) as review_count, 
            AVG(r.stars) as stars, i.image, p.location 
      FROM content_type t 
           INNER JOIN product p ON t.content_type_id=c.content_type_id 
                 LEFT JOIN product_review r ON p.product_id=r.product_id 
                 LEFT JOIN image i ON p.uid=i.reference_page_or_product 
    

    AND p.active=1

      ORDER BY RAND() 
    

    【讨论】:

    • 包含的链接确实解决了标题中的问题......清楚地表明它是可能的。包含的引用显示了他的示例代码中的一个错误。
    • 如果您想获得支持,您应该为该错误提供修复。
    • @Berge JOIN 条件中的 AND 子句本身并没有错。虽然尚不清楚 OP 想要哪些行,但将该条件放在主查询上而不是 JOIN 实际上可能会导致 fewer 行,而不是 more .
    • @PatrickQ 放错地方了:要么应该添加到内部连接中,要么添加到 where 子句中。
    • @Adder 正如我的评论所指出的,这仅取决于 OP 想要哪些行,这仍不清楚。正如问题中所写,OP 只会在产品处于活动状态的情况下获取图像数据(但仍会获取产品数据)。这没有什么。将该条件放在其他任何地方只会导致更少的结果行,因为所有匹配项都是必需来满足该条件的。通过加入image 连接,仍然会返回不满足该条件的行,只是没有图像数据。 OP 想要 more 结果行,而不是 less
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多