views:

52

answers:

1

If you want the relevance and also the results to be sorted by relevance the common format of a FULLTEXT query is:

SELECT name, MATCH(name) AGAINST('Bob') AS relevance FROM users WHERE MATCH(name) AGAINST('Bob')

As a developer I always like to make my code DRY(don't repeat yourself). Is there any reason not to write the query as:

SELECT name, MATCH(name) AGAINST('Bob') AS relevance FROM users HAVING relevance > 0 ORDER BY relevance DESC

It seems to return the same results but should I be worried about the ORDER BY causing the query to be slower? Are these queries equivalent?

Specifying MATCH() twice does not decrease performance as noted in the MySQL manual.

Natural Language Full-Text Searches

To achieve this result, you should specify MATCH() twice: once in the SELECT list and once in the WHERE clause. This causes no additional overhead, because the MySQL optimizer notices that the two MATCH() calls are identical and invokes the full-text search code only once.

+1  A: 

Unfortunately, according to the MySQL SELECT documentation, "the HAVING clause is applied nearly last, just before items are sent to the client, with no optimization."

The difference is that the first query will use the fulltext index to calculate the relevance only for rows that have 'Bob' in name. The second query will calculate the relevance for all rows, then throw out most of them (possibly after sorting the entire table). Therefore, the second query is significantly slower. Even if you put the ORDER BY clause onto the first query, it will still be faster than using HAVING:

SELECT name, MATCH(name) AGAINST('Bob') AS relevance
FROM users
WHERE MATCH(name) AGAINST('Bob')
ORDER BY relevance DESC

In general, "do not use HAVING for items that should be in the WHERE clause."

eswald
I tried using a WHERE relevance > 0 but then I got this error Unknown column 'relevance' in 'where clause'
ejunker
True. The WHERE clause is computed *before* the SELECT expressions, so it can't use any aliases for those expressions. The HAVING clause is executed after, so it can use those aliases; however, only the WHERE clause lets MySQL optimize away useless calculations.In this case, DRY or speed: take your pick.
eswald