2013-10-23 3 views
5

Znalazłem wiele pytań, które wymagają ilości wyświetleń, ale żaden z nich nie pyta o to samo, co chcę zrobić.mysql SORTUJ przez liczbę unikalnych dopasowań słów

Dynamicznie generowane (przygotowane-rachunek) kwerenda spowoduje coś takiego:

SELECT * FROM products WHERE 
(title LIKE ? AND title LIKE ?) AND 
(content LIKE ? OR content LIKE ?) AND 
(subtitle LIKE ? AND author LIKE ?) 
ORDER BY relevance LIMIT ?,? 

Kwota słowach wszedł (a więc ilość LIKE) są na tytuł, treść i autor zmienną kwota (w zależności od zapytania wyszukiwania).

Dodałem teraz ORDER BY relevance. Ale chciałbym, żeby to zamówienie było ilością unikalnych słów z dopasowanego pola treści. (Uwaga: Nie w odniesieniu do liczby odwołań, ale od ilości wprowadzonych ciągów w kolumnie , które mają co najmniej jeden mecz).

Przykład tabeli products:

id | title | subtitle | content 
------------------------------------ 
1 | animals | cat  | swim swim swim swim swim swim swim 
2 | canimal | fish  | some content 
3 | food | roasted | some content 
4 | animal | cat  | swim better better swims better something else 
5 | animal | cat  | dogs swim better 

Przykład kwerendy (z przygotowanych sprawozdań wypełnione): (! W odpowiedniej kolejności)

SELECT * FROM products WHERE 
(title LIKE %animal%) AND 
(content LIKE %dog% OR content LIKE %swim% OR content LIKE %better%) AND 
(subtitle LIKE %cat%) 
ORDER BY relevance LIMIT 0,10 

Oczekiwane wyniki:

id  | amount of matches 
----------------- 
5  | 3 (dog, swim, better) 
4  | 2 (swim, better) 
1  | 1 (swim) 

I mieć tabelę Innodb i wersję mysql niższą niż 5,6, dlatego nie mogę używać MATCH...AGAINST. Myślałem, że można to rozwiązać za pomocą WHEN CASE ... THEN. Ale nie mam pojęcia, jak mogę stworzyć to sortowanie.

Odpowiedz

1

Można to zrobić na wiele sposobów, na przykład

ORDER BY SIGN(LOCATE('dog',content))+ 
     SIGN(LOCATE('swim',content))+ 
     SIGN(LOCATE('better',content)) DESC 

SQLFiddle demo

lub z CASE

ORDER BY 
CASE WHEN content LIKE '%dog%' 
     THEN 1 
     ELSE 0 
END 
+ 
CASE WHEN content LIKE '%swim%' 
     THEN 1 
     ELSE 0 
END 
+ 
CASE WHEN content LIKE '%better%' 
     THEN 1 
     ELSE 0 
END 

DESC 
+0

Czy spełnienie ma jakieś znaczenie? A jeśli chcę dodać liczbę (*) wszystkich znalezionych wierszy (dla stronicowania), czy to możliwe? – Pepe

+0

To zależy ... Myślę, że drugi sposób będzie szybszy [Zlokalizuj] (http://sqlfiddle.com/#!2/d41d8/23552) vs [Lubię] (http://sqlfiddle.com/#!2/d41d8/23554). A także tutaj ten sam wynik: [MySQL LIKE vs LOKALIZUJ] (http://stackoverflow.com/questions/7499438/mysql-like-vs-locate) – valex

+0

Prawdopodobnie będę używał drugiej drogi, ponieważ% -signs są już dołączone do słów, więc nie mogę użyć pierwszej metody. Czy mogę napisać przypadek, gdy zawartość jest podobna? (dla przygotowanych oświadczeń)? A czy ELSE 0 trzeba dodać? – Pepe

1

Sprawdź takiego.