mysql,JOIN和排除匹配

时间:2011-02-01 14:03:59

标签: mysql database database-design

我有一个系统,可以让我处理书籍和人们在寻找书籍时可以做的研究。

数据库是mysql,我有两个主要表BOOKSRESEARCHES

BOOKS(id *int*, author *string*, title *string*, price *string*, tags *set('sci-fi', 'literature', 'theatre', 'drama', 'romance', 'recent', ...)*, ...) 

RESEARCHES is (researches_id, price_max, author, ...)

当我在数据库中添加一本书时,我希望得到与这本新书相匹配的研究。 由于人们可以在他们的研究中使用很多标签(超过30个),我决定创建另一个表格,而不是在RESEARCHES中使用标签列,这可能是SET, 因为我认为SET列上没有索引,因此我的数据库无法快速处理我的请求。

RESEARCHES_TAGS(id, researches_id, tag).

如果我添加PK Dick的书,标签为'sci-fi','drama',我希望将标签为NULL或标签('sci-fi','')进行研究戏剧')并排除 与其他标签一起研究。

所以我正在做以下请求:

SELECT * FROM RESEARCHES
LEFT JOIN RESEARCHES_TAGS ON RESEARCHES.researches_id = RESEARCHES_TAGS.researches_id AND RESEARCHES_TAG.tag IN ('literature', 'theatre', 'romance', ...)
WHERE RESEARCHES_TAGS.tag IS NULL

请注意,指定的tags数组不包含标记'sci-fi','drama'。

我的问题是:有更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

我认为重点是排除与标签“文献”,“剧院”,“浪漫”等相关联的行,并且只保留没有标准的行或符合匹配条件的行(sci)电影或戏剧或两者兼而有之)。 你提出的查询恰恰相反。

我自己通常会使用LEFT JOIN j WHERE j.id IS NULL语句,但这显然是一种反直觉的解决方案。

也许重新定义表结构会允许更简单和/或更快的查询?让我们重新解释一下这个问题......

Will asks for any products
Jane asks for products with at least A and B
John asks for products with at least C
Yael asks for products with at least A and C
Mark asks for products with at least A

您拥有符合A和B要求的产品。你是谁卖给它的?

答案是Will,Jane和Mark,你怎么把它放在表格和查询中?

如果您只有几种类型的要求,则为每个要求添加一个字段,并要求WHERE C = 0 AND D = 0,因为您不想联系需要您不具备的内容的人。但是如果你有越来越多的标准呢?你不能只是继续添加字段。使用set字段将排除使用索引的可能性。

答案 1 :(得分:0)

您应该将JOIN条件与WHERE条件分开。此外,INNER JOIN对我来说更有意义,因为如果没有相应的RESEARCHES_TAGS行,您将没有RESEARCHES行...对吗?

SELECT * FROM RESEARCHES
INNER JOIN RESEARCHES_TAGS ON RESEARCHES.researches_id = RESEARCHES_TAGS.researches_id 
WHERE RESEARCHES_TAGS.tag IS NULL OR tag IN ('literature', 'theatre', 'romance', ...)

此外......您应该澄清此查询以指明哪个表tag属于。