我正在使用MySQL
,我有一个歌曲的SQL数据库,其中一个表格包含一列歌曲的8列信息。每一行代表歌词中的一个单词:
songSerial
- 歌曲的序列号
songName
- 歌曲名称
word
- 歌曲歌词中的单词
row_number
- 找到该字词的行数
word_position_in_row
- 单独行中的单词编号
house_number
- 该字所属的房屋编号
house_row
- 在
word_number
- 所有歌曲歌词中的字数
一排的例子:{4,科学家,秘密,8,4,2,1,37}
现在我想查询包含一组单词的所有歌曲。例如,所有带有句子的单词:"我爱你"在他们中。 必须按顺序,而不是来自不同的行或房屋。
以下是我的oneDrive中用于创建数据表和大约400行的脚本: TwoTextScriptFilesAndTheirZip
有人可以帮忙吗?
谢谢
答案 0 :(得分:1)
一种方法是使用join
s:
select s.*
from songwords sw1 join
songwords sw2
on sw2.songSerial = sw1.songSerial and
sw2.word_number = sw1.word_number + 1 join
songwords sw3
on sw3.songSerial = sw2.songSerial and
sw3.word_number = sw2.word_number + 1
where sw1.word = 'I' and sw2.word = 'love' and sw3.word = 'you';
或者,如果您愿意:
where concat_ws(' ', sw1.word, sw2.word, sw3.word) = 'I love you'
从优化角度来看情况更糟(使用word
的索引无法帮助提高性能),但很清楚查询正在做什么。
此类型的搜索建议使用full text index。唯一需要注意的是,无论长度如何,您都需要删除停用词列表并索引所有单词。 (“我”和“你”是停止词的典型例子。)
答案 1 :(得分:0)
对于大型表,这是一种昂贵的方法,假设word
不为空,我们可以这样做:
SET group_concat_max_len = 16777216 ;
SELECT t.song_serial
, t.house_number
, t.row_number
FROM mytable t
GROUP
BY t.songserial
, t.house_number
, t.row_number
HAVING CONCAT(' ',GROUP_CONCAT(t.word ORDER BY t.word_position_by_row),' ')
LIKE CONCAT('% ','I love you',' %')
我们肯定想要一个合适的索引,例如
... ON `mytable` (`songserial`,`house_number`,`row_number`,`word`)
如果短语中的一个单词不常见,我们可能首先搜索该不常用的单词来优化一点,然后将所有单词放在同一行...
SELECT t.song_serial
, t.house_number
, t.row_number
FROM ( SELECT r.songserial
, r.house_number
, r.row_number
FROM mytable r
WHERE r.word = 'love'
GROUP
BY r.word
, r.songserial
, r.house_number
, r.row_number
) s
JOIN mytable t
ON t.songserial = s.songserial
AND t.house_number = s.house_number
AND t.row_number = s.row_number
GROUP
BY t.songserial
, t.house_number
, t.row_number
HAVING CONCAT(' ',GROUP_CONCAT(t.word ORDER BY t.word_position_by_row),' ')
LIKE CONCAT('% ','I love you',' %')
内联视图s
将受益于覆盖索引,其中word为前导列
... ON `mytable` (`word`,`songserial`,`house_number`,`row_number`)
答案 2 :(得分:0)
你寻找这些单词和相对搜索位置:1 = I,2 =爱,3 =你。让我们将它们与两首歌曲进行比较:
And I love, love, love you real pos: 1 2 3 4 5 6 search pos: - 1 2 2 2 3 diff: - 1 1 2 3 3 I miss you and I love you real pos: 1 2 3 4 5 6 7 search pos: 1 - 3 - 1 2 3 diff: 0 - 0 - 4 4 4
如果我们查看第一行的位置增量,我们得到1(两次),2(一次)和3(两次)。
对于第二行,我们得到增量0(两次)和4(三次)。
因此,对于第二首歌曲,我们找到一个与搜索词一样多的匹配的delta,而不是第一行。第二行是匹配。
这是查询。我假设我们有一个临时表search
填充了搜索词和相对位置以便于阅读。
select distinct w.songserial, w.songname, w.house_number
from words w
join search s on s.word = w.word
group by
w.songserial, w.songname, w.row_number, w.house_number, w.house_row, -- song line
w.word_position_in_row - s.pos -- delta
having count(*) = (select count(*) from search);
此查询基于:
songserial
+ songname
+ house_number
songserial
+ songname
+ row_number
+ house_number
+ house_row
这可能是错的;我不知道参考歌曲的房子和门牌号是什么意思。但这很容易调整。