2009-11-16 33 views
1

我有這張表,其中包含許多與圖書相關的字段,包括關鍵字。 Book_ids是主鍵。假設我有一本有六個關鍵詞描述的書,現在我該如何搜索所有其他具有兩個或更多相同關鍵字的書?對於2個或更多匹配的情況下的SQL

我現在大致是這樣的:

select book_id 
from book_fields 
where keyword in (select keyword from book_fields where book_id='123') 

的目的是讓基於關鍵字的同類書籍粗糙的建議。如果可能,我想用SQL來做到這一點。

澄清: 這個想法是使用多個關鍵字將書籍與其他書籍進行匹配。所有書的所有關鍵字都在book_fields表中。沒有機會觸及架構,RDMS是Oracle。

+1

你必須更明確(至少給我們一個提示)就如何關鍵字字段或字段是結構化的。希望它們在單獨的表中,每個記錄有一個關鍵字。如果不是,他們在不同的領域?或者在單個字段中用逗號分隔? – 2009-11-16 17:53:18

+0

您需要發佈您的表定義(列名,數據類型和內容),示例數據和所需的結果。你沒有提供足夠的信息來獲得答案。 – 2009-11-16 17:53:54

+1

您使用的是什麼'RDBMS'? – Quassnoi 2009-11-16 18:07:40

回答

2

假設你有一個一對多的表,KeywordsToBooks,具有以下模式:

的BookID INT
關鍵字varchar

將兩列作爲PK,BookID作爲FK添加到您的Books表,並傳遞@B ookToMatchID只要你想匹配的參數書的ID,這是我會怎麼做:

SELECT BookID, COUNT(BookID) AS KeywordMatches 
FROM KeywordsToBooks 
WHERE BookID <> @BookToMatchID AND Keyword IN (
    SELECT Keyword 
    FROM KeywordsToBooks 
    WHERE BookID = @BookToMatchID) 
GROUP BY BookID 
HAVING COUNT(BookID) >= 2 

至於其他的建議,如果這沒有幫助,你可以發表你的架構的相關位請?

+0

您瞭解我的想法,這正是我的目標。 – Illotus 2009-11-17 10:24:31

0

通過創建一個包含所有關鍵字的表,可以更好地解決此問題。

是否可行?

2

假設的書籍存儲在表命名books

SELECT * 
FROM books bo 
WHERE (
     SELECT 1 
     FROM book_fields bf 
     JOIN book_fields br 
     ON  bf.keyword = br.keyword 
     WHERE br.book_id = 123 
       AND bf.book_id = bo.id 
     LIMIT 1, 1 
     ) = 1 
3
BEGIN; 

CREATE SCHEMA books; 
SET search_path TO books; 

CREATE TABLE book_fields (
    book_id INT NOT NULL 
, keyword VARCHAR(30) NOT NULL 
, PRIMARY KEY (book_id, keyword) 
); 

INSERT INTO book_fields (book_id, keyword) 
VALUES 
    (10, 'foo') 
, (10, 'bar') 
, (10, 'baz') 
, (20, 'foo') 
, (20, 'xxx') 
, (20, 'baz') 
, (30, 'yyy') 
, (30, 'zzz') 
; 

SELECT 
    lhs.book_id AS thisbook 
, rhs.book_id AS otherbook 
, COUNT(rhs.keyword) 
FROM book_fields lhs, book_fields rhs 
WHERE lhs.book_id <> rhs.book_id 
    AND lhs.keyword = rhs.keyword 
GROUP BY lhs.book_id, rhs.book_id 
; 

ROLLBACK; 
+0

+1表示連接的關係純度。這是否使我成爲一名關係人? – outis 2009-11-16 18:26:03

+0

另外,添加'HAVING COUNT(rhs.keyword)> 1'來滿足OP對兩個或更多關鍵字共同的要求。 – outis 2009-11-16 18:30:27

1

爲了獲得更好的性能,請大致ristonj暗示什麼,但要避免使用IN子句:

SELECT book_id, COUNT(*) 
    FROM book_fields b 
WHERE EXISTS (SELECT 1 
       FROM book_fields a 
       WHERE a.keyword = b.keyword 
        AND a.book_id = '123') 
GROUP BY book_id 
HAVING COUNT(*) >= 2 
+1

感謝您的提示。這使得這個小查詢成爲查詢的一個數量級差異。 – Illotus 2009-11-17 10:25:27

+0

沒問題,很高興它幫助你。 – Tom 2010-07-06 13:53:31