2013-10-23 17 views
5

Ich habe viele Fragen gefunden, die nach Menge von Auftritten fragen, aber keine, die dasselbe fragen, wie ich es tun möchte.mysql SORTIEREN NACH Anzahl der eindeutigen Worttreffer

Ein dynamisch generiert (hergestellt-Anweisung) Abfrage in etwa wie folgt führen:

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 ?,? 

Die Menge der Wörter eingegeben, (und so die Menge an LIKE) sind für Titel, Inhalt und eine variable Autor Menge (abhängig von der Suchanfrage).

Jetzt habe ich eine ORDER BY relevance hinzugefügt. Aber ich möchte, dass diese Reihenfolge die Anzahl der eindeutigen Wörter aus dem Inhaltsfeld ist, die übereinstimmen. (Hinweis: Nicht auf die Anzahl der Erscheinungen, sondern auf die Menge der eingegebenen Zeichenfolgen in der content Spalte, die mindestens eine Übereinstimmung haben).

Beispieltabelle 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 

Beispiel Abfrage (mit vorbereiteten Anweisungen ausgefüllt?): (! In der richtigen Reihenfolge)

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 

Erwartete Ergebnisse:

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

I habe eine Innodb-Tabelle und MySQL-Version niedriger als 5,6, daher kann ichnicht verwenden 10. Ich dachte, das könnte mit WHEN CASE ... THEN gelöst werden. Aber ich habe keine Ahnung, wie ich diese Sortierung erstellen könnte.

Antwort

1

Sie können es in vielerlei Hinsicht für

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

SQLFiddle demo

oder mit 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

leistungs weise irgendein unterschied? Und wenn ich eine Zählung (*) aller gefundenen Zeilen (für Paginierung) hinzufügen möchte, ist das möglich? – Pepe

+0

Es hängt davon ab ... Ich denke, der zweite Weg wird schneller sein [Lokalisieren] (http://sqlfiddle.com/#!2/d41d8/23552) vs [Gefällt mir] (http://sqlfiddle.com/#!2/d41d8/23554). Und auch hier das gleiche Ergebnis: [MySQL LIKE vs LOCATE] (http://stackoverflow.com/questions/7499438/mysql-like-vs-locate) – valex

+0

Ich werde wahrscheinlich den zweiten Weg verwenden, wie die% -Zeichen sind bereits an die Wörter angehängt, so kann ich die erste Methode nicht verwenden. Kann ich FALL WENN Inhalt wie schreiben? (für vorbereitete Aussagen)? Und muss der ELSE 0 hinzugefügt werden? – Pepe

1

prüfen wie diese.

SELECT id,CONCAT_WS('-',COUNT(LENGTH(content) - LENGTH(REPLACE(content, ' ', '')) + 1),REPLACE(content,' ',',')) AS amount of matches FROM products 
     WHERE 
     (title LIKE %animal%) AND 
     (content LIKE %dog% OR content LIKE %swim% OR content LIKE %better%) AND 
     (subtitle LIKE %cat%) 
     GROUP BY id 
ORDER BY id 
Verwandte Themen