自联接找到行位置

时间:2011-05-07 15:08:20

标签: mysql sql

我有一个单词列表和另一个表,其中包含每个单词中使用的所有字符。对于例如如果有一个单词“test”,那么单词characters表将有4行t,e,s,t。

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)

很容易找到“e”位于第二位置的单词。 但是如何找到“e”位于第二位置且“a”位于第五位的字词? 可能有几个(最多8个)这样的条件。

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)

以下是相关表格。

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')

更新

是否可以在同一查询中返回count或max(char_seq)? 所以对于前者。在下面的答案中,它应该看起来像......

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

3 个答案:

答案 0 :(得分: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';

结果:

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

无法立即想出一种处理任何可能条件的优雅方式 - 也许其他人对此有所了解。

答案 1 :(得分:2)

对于任意数量的条件(甚至包括条件的任意数量的匹配)创建表条件(id,match_id,position,char)并使用查询:

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

返回具有相同match_id的一组给定条件的单词中匹配字符的数量(此处为1)。

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

答案 2 :(得分:1)

如果我必须按原样搜索word_list表而不必使用chars表,我会这样做。

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