2013-10-23 11 views
5

Ho trovato molte domande che richiedono quantità di apparizioni, ma nessuna che richieda la stessa cosa che desidero fare.mysql SORT BY quantità di corrispondenze di parole univoche

Un generato dinamicamente (preparato-statement) interrogazione si tradurrà in qualcosa di simile:

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

La quantità di parole è entrato, (e quindi la quantità di LIKE) sono per il titolo, il contenuto e autore di una variabile importo (a seconda della query di ricerca).

Ora ho aggiunto un ORDER BY relevance. Ma vorrei che questo ordine fosse la quantità di parole uniche del campo di contenuto che corrispondono. (Nota: non sulla quantità di apparenze, ma sulla quantità di stringhe immesse nella colonna content che hanno almeno una corrispondenza).

tabella Esempio 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 

interrogazione Esempio (con istruzioni preparate compilati?): (! In ordine corretto)

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 

Risultati attesi:

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

I avere una tabella Innodb e una versione mysql inferiore a 5.6, quindi non posso usare MATCH...AGAINST. Stavo pensando che questo potrebbe essere risolto con WHEN CASE ... THEN. Ma non ho idea di come potrei creare questo ordinamento.

risposta

1

lo si può fare in molti modi, ad esempio

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

SQLFiddle demo

o con 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

prestazioni saggia qualche differenza? E se desidero aggiungere un conteggio (*) di tutte le righe trovate (per l'impaginazione), è possibile? – Pepe

+0

Dipende ... Penso che il secondo modo sarà più veloce [Locate] (http://sqlfiddle.com/#!2/d41d8/23552) vs [Mi piace] (http://sqlfiddle.com/#!2/d41d8/23554). E anche qui lo stesso risultato: [MySQL LIKE vs LOCATE] (http://stackoverflow.com/questions/7499438/mysql-like-vs-locate) – valex

+0

Preferibilmente userò il secondo modo, dato che i% -signs sono già aggiunto alle parole, quindi non posso usare il primo metodo. Posso scrivere CASE QUANDO contenuto? (per dichiarazioni preparate)? E l'ELSE 0 deve essere aggiunto? – Pepe

1

controllare come questo.

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 
Problemi correlati