我有一个简单的全文搜索查询:
SELECT *, MATCH(col1,col2,col3) AGAINST ('keywords' IN BOOLEAN MODE) AS relev FROM table1 WHERE relev > 0 ORDER BY relev DESC
技术上有效,但它也返回相关性为0的结果。
我试图使用:
relev
但这告诉我relev
是无效的列名。
有没有办法排除MATCH(..) AGAINST(..)
为0的结果,而不必在WHERE
子句中再次使用{{1}}?不这样做基本上再次重复全文搜索并花费两倍的时间吗?
答案 0 :(得分:1)
您可以改为使用having
子句:
SELECT t.*,
MATCH(col1, col2, col3) AGAINST ('keywords' IN BOOLEAN MODE) AS relev
FROM table1 t
HAVING relev > 0
ORDER BY relev DESC;
SQL(通常)不允许在WHERE
子句中使用列别名。但是,MySQL会在HAVING
子句中允许它们(并非所有数据库都这样)。这对于这种情况很方便。
答案 1 :(得分:0)
The MySql docs 暗示使用 HAVING
将导致仅在评估所有相关性分数后进行过滤。
HAVING 子句几乎最后应用,就在项目被发送到客户端之前,没有优化。 (LIMIT 在 HAVING 之后应用。)
和
<块引用>不要对应该在 WHERE 子句中的项目使用 HAVING。
重复MATCH()
is actually better
要实现此结果,您应该指定 MATCH() 两次:一次在 SELECT 列表中,一次在 WHERE 子句中。这不会导致额外的开销,因为 MySQL 优化器注意到两个 MATCH() 调用是相同的,并且只调用一次全文搜索代码。
我的实验和 this other StackOverflow QA 证实了这一点。
我也尝试使用内部查询
SELECT * FROM (
SELECT textColumn, MATCH(textColumn) AGAINST('searchWord' IN BOOLEAN MODE) as relevance
FROM table
)
WHERE relevance > 0
其性能与 HAVING
版本一样差。
我希望有一个替代方案的原因不是在查询中重复我自己 - DRY。
不幸的是,我认为不可能在没有性能损失的情况下避免重复自己,所以最后我选择了双 MATCH() AGGAINST()
。