2009-11-16 5 views
1

J'ai ce tableau qui a beaucoup de domaines liés au livre, y compris les mots-clés. Book_ids sont des clés primaires. Disons que j'ai un livre avec six mots-clés le décrivant, comment puis-je rechercher tous les autres livres qui ont deux ou plusieurs mots-clés identiques?SQL pour les cas avec 2 ou plus hits

Ce que j'est maintenant à peu près ceci:

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

Le but est d'obtenir des recommandations brutes de livres similaires à base de mots-clés. Je voudrais le faire avec SQL si possible.

Pour clarifier: L'idée est de faire correspondre un livre à d'autres livres en utilisant plus d'un mot-clé. Tous les mots-clés de tous les livres étaient dans la table book_fields. Aucune chance de toucher le schéma et RDMS était Oracle.

+1

Vous devez être plus explicite (au moins, nous donner un indice) à la façon dont le champ mot-clé ou les champs sont structurés. Heureusement, ils sont dans une table séparée avec un mot-clé par enregistrement. Si non, sont-ils dans des champs séparés? Ou délimité par des virgules dans un seul champ? –

+0

Vous devez publier votre définition de table (noms de colonnes, types de données et contenu), des exemples de données et les résultats souhaités. Vous n'avez pas donné assez d'informations pour avoir une réponse. –

+1

Qu'est-ce que 'RDBMS' utilisez-vous? – Quassnoi

Répondre

2

En supposant que vous avez un à plusieurs table, KeywordsToBooks, ayant le schéma suivant:

BookID int
Mot-clé varchar

avec les deux colonnes PK, BookID en tant que FK dans votre table Books et en passant @B ookToMatchID l'ID du livre que vous souhaitez correspondre en tant que paramètre, voici ce que je ferais:

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 

Comme autre est suggéré, si cela ne fonctionne pas, vous pouvez afficher les bits correspondants de votre schéma S'il vous plaît?

+0

Vous avez lu dans mes pensées, c'est exactement ce que je visais. – Illotus

0

Ce problème peut être mieux résolu en créant une table qui contient tous les mots-clés.

Est-ce faisable?

2

En supposant que les livres sont stockés dans la table nommée 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 pour la pureté relationnelle des jointures. Est-ce que cela fait de moi un relationniste? – outis

+0

De plus, ajoutez 'HAVING COUNT (rhs.keyword)> 1' pour répondre aux besoins d'OP pour deux mots-clés ou plus en commun. – outis

1

Pour de meilleures performances, ne peu près ce que ristonj suggère, mais évitez d'utiliser la clause 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

Merci pour le conseil. Cela a fait une différence d'ordre de grandeur dans la requête dont fait partie cette petite requête. – Illotus

+0

Pas de problème, content que ça vous a aidé. – Tom

Questions connexes