【问题标题】:Left Join not working (MySQL)左连接不起作用(MySQL)
【发布时间】:2010-07-27 00:04:16
【问题描述】:

我有一个 Books 表,用于存储图书数据(ISBN、标题、作者等)。为了区分哪些书是彼此的版本,我有一个字段 Edition_Group_ISBN,它是组中的任意 ISBN。

我无法获得这个查询,它应该根据 ISBN 提供图书数据和其他版本的数量:

   SELECT *, Editions_Count 
     FROM Books 
LEFT JOIN ((SELECT Edition_Group_ISBN, COUNT(*) AS Editions_Count 
              FROM Books 
             WHERE Edition_Group_ISBN IN (SELECT Edition_Group_ISBN 
                                            FROM Books)
             GROUP BY Edition_Group_ISBN) AS b 
       ) ON (Books.Edition_Group_ISBN = b.Edition_Group_ISBN 
           AND Books.Edition_Group_ISBN != NULL) 
    WHERE ISBN = 9780140447897

查询给出了 9780140447897 的图书数据,但给出的 Editions_Count AS NULL,表明 LEFT JOIN 不起作用。

【问题讨论】:

  • 我认为您需要另一个表来跟踪版本分组;使用一个任意的 ISBN 为我敲响了警钟。
  • @staticsan 我确实觉得以这种方式存储它有点奇怪,但实际的缺点是什么?
  • 优点是:1-更容易将数据加载到数据库中。使用唯一 ID 2 会更困难 - 它节省了一些数据库空间
  • 给出的答案适用于一本书。我想知道是否可以将它们写成与多个 ISBN 一起使用的方式。
  • 缺点源于您重新利用 ISBN 的事实。您的代码还必须注意 ISBN 也可以表示所有版本,对于其中一个版本,它与 ISBN 相同。

标签: mysql join left-join


【解决方案1】:

试试这个更简单的查询:

SELECT b.*, COUNT(*) AS Editions_count
FROM Books b JOIN Books g USING (Edition_Group_ISBN)
WHERE b.ISBN = 9780140447897
GROUP BY b.book_id;

我认为您使问题变得比您需要的要困难得多。您的原始查询充满了令人困惑的子查询,其中至少有一个是完全多余的。


你的cmets:

是的,以这种方式将 ISBN 与多个值进行比较可以正常工作:

SELECT b.*, COUNT(*) AS Editions_count
FROM Books b JOIN Books g USING (Edition_Group_ISBN)
WHERE b.ISBN IN (9780140447897, 9781934356555)
GROUP BY b.book_id;

COUNT(*) 仅支持普通通配符*,这意味着计算组中的所有行。

或者您可以使用特定的表达式,例如COUNT(g.Edition_Group_ISBN),这意味着计算组中该表达式为非空的所有行。

但您不能使用g.*,因为它不明确。它是否计算组中的所有行? (如果是这样,只需使用COUNT(*))它是否计算组中的非空行?无论如何,这意味着什么 - 计算 g 中的 all 列不为 null 或 g 中的 any 列不为 null 的行数?由于这些原因,COUNT(g.*) 在 SQL 语言中根本不是合法的构造。

【讨论】:

  • GROUP BY 子句只在 MySQL 中就足够了;其他 DBMS 会让您引用 Books 表中的所有列(“b”别名)。由于这个问题被标记为 MySQL,这不是一个直接的问题,但为了一般性,应该注意(或者你可以将它们指向一本名为“SQL Anti-Patterns”的书)。
  • 比尔,有没有办法让这个查询与提供的多个 ISBN 一起工作?
  • 我试过了,但由于 COUNT(g.*) SELECT b.*, COUNT(g.*) AS Editions_count FROM Books b JOIN Books g USING (Edition_Group_ISBN) WHERE b. ISBN IN(9780140447897)
  • @Jonathan:是的,谢谢,MySQL 对 GROUP BY 比标准 SQL 和大多数其他实现更宽容。 SQLite 也以这种方式放纵。
【解决方案2】:

查询似乎包含许多重言式 - 总是正确的陈述。

我认为您可以将其简化为

 SELECT books.*, b.Editions_Count 
     FROM Books 
LEFT JOIN ((SELECT Edition_Group_ISBN, COUNT(*) AS Editions_Count 
              FROM Books 
              GROUP BY Edition_Group_ISBN) AS b 
       ) ON (Books.Edition_Group_ISBN = b.Edition_Group_ISBN) 
 WHERE ISBN = 9780140447897

子选择 (WHERE .. IN) 和 JOIN 条件 ID!=NULL 是多余的。

您可以通过在 Edition_Group_ISBN 上执行自加入来实现相同的目的:

SELECT b.*, count(b2.*)
FROM Books b INNER JOIN Books b2 ON (b.Edition_Group_ISBN=b2.Edition_Group_ISBN)
GROUP BY b.ISBN
HAVING b.ISBN = ...;

编辑: 解决方法是删除 JOIN 条件 Edition_Group_ISBN!=NULL,因为此表达式将始终为假。 (!= 的 NULL 操作数返回 NLLL 结果。)这使整个连接条件为 NULL (false),因此左连接失败。

【讨论】:

  • 其实ID != NULL 是不正确的,应该是ID IS NOT NULL
  • 感谢您接受。这可能就是它不起作用的原因。比较运算符 != 如果其操作数之一为 NULL,则返回 NULL。我太忙于清理了,第一次没有注意到。
  • George,由于该修复,查询工作正常。现在,在选择答案之前,我将花一些时间来测试这里建议的一些更好的查询。
  • 嗯,我真的很好奇为什么 ID != NULL 会阻止查询工作..
  • 请看我的编辑。 != 的 NULL 操作数会产生 NULL 结果。
猜你喜欢
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-02
  • 2012-09-10
  • 2019-02-02
  • 1970-01-01
相关资源
最近更新 更多