2011-02-01 38 views
2

我有一個系統,它允許我處理書籍和研究人員在他們查找書籍時可以執行的操作。mysql,加入和排除匹配

數據庫是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迪克添加了一本書,與標籤「科幻」,「電視劇」,我想有標籤的研究作爲NULL或標籤在(「科幻」, '戲劇'),並排除 研究與其他標籤。

所以我做以下請求:

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 

注意,指定的標籤數組不包含標籤「科幻」,「戲劇」。

我的問題是:有沒有更好的解決方案?

回答

0

您應該將您的JOIN標準與WHERE標準分開。另外,INNER JOIN對我來說更有意義,因爲如果沒有對應的RESEARCHES行,您將不會有RESEARCHES_TAGS行...對嗎?

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屬於哪個表。

1

我認爲重點是排除與標籤「文學」,「戲劇」,「浪漫」等鏈接的行,並保持行沒有標準,或與匹配標準(科幻或戲劇或都)。 您提出的查詢是相反的。

我自己通常會用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要求的產品。你要賣給誰?

答案是威爾,簡和馬克,你如何把它放在表和查詢?

如果您只有幾種類型的要求,請爲每個要求輸入一個字段,並要求WHERE C = 0 AND D = 0,因爲您不想聯繫那些需要您沒有的東西的人。但是如果你有越來越多的標準呢?你不能只是添加字段。而使用set字段將排除使用索引的可能性。

+0

您改寫問題的方式非常好,符合我的顧慮。 我實際上有越來越多的標準列表,我無法爲每個標準創建列。 那麼,是的,如何以比「LEFT JOIN j WHERE j.id IS NULL」語句更恰當的方式來獲得Will,Jane和Mark的研究? – marc 2011-02-02 08:51:28