2015-02-18 5 views
4

Я действительно не знал, что назвать это.MySQL Группировка похожих строк на основе записей во второй таблице

У меня есть несколько таблиц структурированы как этот

А "предложения" таблица

id | sentence  | ... 
---------------------------- 
1 | See Spot run  | ... 
2 | See Jane run  | ... 
3 | Jane likes cheese | ... 

А "слова" стол

id | word (unique) 
---------- 
1 | See 
2 | Spot 
3 | run 
4 | Jane 
5 | likes 
6 | cheese 

и "word_references" стол

sentence_id | word_id 
--------------------- 
      1 | 1 
      1 | 2 
      1 | 3 
      2 | 1 
      2 | 3 
      2 | 4 
      3 | 4 
      3 | 5 
      3 | 6 

I хотите вернуть список пар предложений, которые похожи друг на друга на основе общих слов, упорядоченных по сходству. Поэтому он должен вернуть:

one | two | similarity 
---------------------- 
1 | 2 | 2 
2 | 3 | 1 

, потому что предложения 1 и 2 доля двух слов: «Смотри» и «бежать», в то время как предложения 2 и 3 доля одного слова: «Джейн».

ответ

2

Этот запрос должен решить проблему:

SELECT r1.sentence_id AS one, 
     r2.sentence_id AS two, 
     Count(*)  AS similarity 
FROM word_references r1 
     INNER JOIN word_references r2 
       ON r1.sentence_id < r2.sentence_id 
        AND r1.word_id = r2.word_id 
GROUP BY r1.sentence_id, 
      r2.sentence_id 

это дает:

one | two | similarity 
---------------------- 
1 | 2 | 2 
2 | 3 | 1 

sqlfiddle here

Если изменить выражение r1.sentence_id < r2.sentence_id к r1.sentence_id <> r2.sentence_id, вы получите обе стороны отношение:

one | two | similarity 
---------------------- 
1 | 2 | 2 
2 | 3 | 1 
2 | 1 | 2 
3 | 2 | 1 
+0

Чтобы сделать его немного аккуратнее и, возможно, быстрее: использовать 'внутренний join' вместо' левой join', положить оба условия 'r1.sentence_id

+0

@VladimirBaranov thx, имеет смысл –

+0

Отлично работает. Его довольно медленно, но это следует ожидать при выполнении операции O (n^2) в моей среде. Интересно, есть ли какой-либо индекс, который можно добавить, или другую таблицу, которая может ускорить работу. –

0

Что-то, как это будет работать:

select w1.sentence_id, w2.sentence_id, count(*) as similarity 
from word_references w1 
left join word_references w2 on w1.word_id=w2.word_id and w1.sentence_id<>w2.sentence_id 
where w2.sentence_id is not null 
group by w1.sentence_id, w2.sentence_id 
order by count(*) desc 

Пример вывода:

+ ---------------- + ---------------- + --------------- + 
| sentence_id  | sentence_id  | similarity  | 
+ ---------------- + ---------------- + --------------- + 
| 1    | 2    | 2    | 
| 2    | 1    | 2    | 
| 3    | 2    | 1    | 
| 2    | 3    | 1    | 
+ ---------------- + ---------------- + --------------- + 
4 rows 
Смежные вопросы