2011-05-07 4 views
1

J'ai une table de liste de mots et une autre table qui contient tous les caractères utilisés dans chaque mot. Par exemple s'il y a un mot "test" alors le tableau des caractères du mot aura 4 lignes t, e, s, t.Jointure automatique pour trouver la position de ligne

mysql> select * from word_list; 
+---------+---------+ 
| word_id | word | 
+---------+---------+ 
|  1 | This | 
|  2 | is  | 
|  3 | test | 
|  4 | message | 
|  5 | for  | 
+---------+---------+ 
5 rows in set (0.00 sec) 

mysql> select * from word_chars; 
+----+---------+----------+-----------+ 
| id | word_id | char_seq | word_char | 
+----+---------+----------+-----------+ 
| 1 |  1 |  1 | T   | 
| 2 |  1 |  2 | h   | 
... 
... 

| 19 |  5 |  2 | o   | 
| 20 |  5 |  3 | r   | 
+----+---------+----------+-----------+ 
20 rows in set (0.00 sec) 

Il est facile de trouver le mot où "e" est à la deuxième position. Mais comment puis-je trouver les mots où "e" est à deuxième position et "a" est au cinquième position? Il peut y avoir plusieurs (jusqu'à 8) de telles conditions.

select word from word_list as a inner join word_chars as b on a.word_id = b.word_id 
where word_char = 'e' and char_seq = '2'; 
+---------+ 
| word | 
+---------+ 
| test | 
| message | 
+---------+ 
2 rows in set (0.00 sec) 

Voici les tableaux pertinents.

drop table if exists word_list; 
create table word_list (word_id int not null auto_increment, word varchar(255), primary key (word_id)) ENGINE=InnoDB; 
insert into word_list (word) values ('This'), ('is'), ('test'), ('message'), ('for'); 

drop table if exists word_chars; 
create table word_chars (id int not null auto_increment, word_id int, char_seq int, word_char varchar(50), primary key (id), unique key `word_seq` (word_id, char_seq), foreign key (word_id) references word_list(word_id)) ENGINE=InnoDB; 
insert into word_chars (word_id, char_seq, word_char) values (1, 1, 'T'), (1, 2, 'h'), (1, 3, 'i'), (1, 4, 's'), (2, 1, 'i'), (2, 2, 's'), (3, 1, 't'), (3, 2, 'e'), (3, 3, 's'), (3, 4, 't'), (4, 1, 'm'), (4, 2, 'e'), (4, 3, 's'), (4, 4, 's'), (4, 5, 'a'), (4, 6, 'g'), (4, 7, 'e'), (5, 1, 'f'), (5, 2, 'o'), (5, 3, 'r') 

Mise à jour:

Est-il possible de retourner le compte ou max (char_seq) dans la même requête? Donc par ex. Dans la réponse suivante, il devrait ressembler ...

+---------+ 
| word | count 
+---------+ 
| message | 7 
+---------+ 
+0

J'espère que la colonne 'word_char' est de type' ENUM'. Ce serait très bon pour la performance ** et ** le stockage. – Rudie

Répondre

2
select word from word_list as a 
inner join word_chars as b on a.word_id = b.word_id 
inner join word_chars as c on a.word_id = c.word_id 
where b.word_char = 'e' and b.char_seq = '2' 
and c.word_char = 'a' and c.char_seq = '5'; 

Résultat:

+---------+ 
| word | 
+---------+ 
| message | 
+---------+ 

peut pas immédiatement penser à une façon élégante de gérer un certain nombre de conditions - peut-être quelqu'un D'autre a une idée pour cela.

+0

Merci pour ça. Je vais le faire en PHP. Mais la question a été mise à jour. – shantanuo

+0

sélectionner un mot, compter (mot) ... grouper par mot; devrait le faire – YXD

1

Si je devais rechercher la table word_list telle quelle sans avoir à utiliser la table chars, je le ferais comme ceci.

select word from 
word_list 
where Substring(word,2,1) = 'e' 
and Substring(word,5,1) = 'a' 
2

Pour un certain nombre de conditions (et même un certain nombre de correspondances comprenant des conditions) créer des conditions de table (id, match_id position, char) et utiliser la requête:

SELECT a.word, d.matched FROM 
     (SELECT b.word_id, count(b.id) as matched FROM word_chars b 
     JOIN conditions c 
     ON c.position = b.char_seq 
     AND c.char = b.word_char 
     WHERE c.match_id = 1 
     GROUP BY b.word_id) d 
JOIN word_list a 
ON a.word_id = d.word_id 

pour revenir nombre de caractères correspondants dans un mot pour un ensemble de conditions donné avec le même match_id (1 ici).

+---------+---------+ 
| word | matched | 
+---------+---------+ 
| test |  1 | 
| message |  2 | 
+---------+---------+ 
Questions connexes