2010-07-27 112 views
1

我有一个表书籍,我在那里存放图书资料(国际标准书号的,标题,作者等)。要知道哪些书是对方的版本,我有一个字段版本_组_ISBN,它是组中的任意ISBN。左连接不工作(MySQL的)

我无法得到这个查询,这是为了把书数据并根据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不起作用。

+0

我认为你需要另一个表来跟踪版本分组;使用一个任意的国际标准书号来做它为我敲响警钟。 – staticsan 2010-07-27 00:19:59

+0

@staticsan我确实觉得用这种方式存储它有点奇怪,但实际的缺点是什么? – babonk 2010-07-27 00:27:47

+0

有利的一面是: 1-它的方式更容易地装入数据到数据库中。这将是一个独特的ID更难 2它节省了一点的数据库空间 – babonk 2010-07-27 00:42:03

回答

5

试试这个简单得多查询:

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; 

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


回复您的评论:

是的,它工作正常,以国际标准书号这种方式比较多个值:

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全部列非空或其中任何列中的所有列都是非空的行数?由于这些原因,COUNT(g.*)根本不是SQL语言中的合法构造。

+1

GROUP BY子句只在MySQL中足够;其他DBMS会让你引用Books表中的所有列('b'别名)。由于该问题被标记为MySQL,这不是一个直接的问题,但为了通用性,应该注意(或者您可以将它们指向一本名为“SQL反模式”的书)。 – 2010-07-27 01:06:49

+0

比尔,有没有办法使这个查询工作与提供多个ISBN? – babonk 2010-07-27 01:16:50

+0

我试过这个,但是因COUNT(g。*)而得到一个错误 SELECT b。*,COUNT(g。*)AS Editions_count FROM Books b JOIN Books g USING 9780140447897) – babonk 2010-07-27 01:30:00

1

查询似乎包括一些重言式的 - 这总是真实的陈述。

我想你可以把它简化为

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)和联接条件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,因为这个表达式永远是假的! (!=的空操作数返回NLLL结果。)这会使整个连接条件为NULL(false),因此左连接失败。

+1

实际上'ID!= NULL'是不正确的,并且需要是'ID IS NOT NULL' – 2010-07-27 00:25:38

+0

感谢您选择它。这可能是为什么它不工作。如果其中一个操作数为NULL,则比较运算符!=返回NULL。我忙于清理第一次。 – mdma 2010-07-27 00:31:17

+0

乔治,查询工作得益于该修复。现在我要花一些时间在选择答案之前测试一下这里提出的一些更好的查询。 – babonk 2010-07-27 00:34:22