MySQL Optional LEFT JOIN With MATCH

2020-07-18 11:09发布

问题:

I have the following query, which performs a full text search against two columns in two different tables for the same search term in a MySQL Innodb database;

SELECT Id, 
MATCH (tb1.comment, tb2.comment) AGAINST (+'search term' IN BOOLEAN MODE) AS Relevance
FROM tbl1
LEFT JOIN tb2 ON tb1.Id = tb2.Id
WHERE MATCH (tb1.comment, tb2.comment) AGAINST (+'search term' IN BOOLEAN MODE) 
HAVING Relevance > 0 

If I perform the MATCH on just tb1.comment it works fine and I get back the relevant search terms, but I want to perform it against both columns.

However because the other table is optional with the LEFT JOIN it doesn't return anything, if there is no matching Ids. Any ideas on how to overcome this problem ?

回答1:

I managed to figure out the following work around that appears to perform fine and give the results I desire;

    SELECT Id, 
    MATCH (tb1.comment) AGAINST (+'search term' IN BOOLEAN MODE) AS Relevance1,
    MATCH (tb2.comment) AGAINST (+'search term' IN BOOLEAN MODE) AS Relevance2
    FROM tbl1
    LEFT JOIN tb2 ON tb1.Id = tb2.Id
    WHERE (MATCH (tb1.comment) AGAINST (+'search term' IN BOOLEAN MODE) 
    OR MATCH ( tb2.comment) AGAINST (+'search term' IN BOOLEAN MODE))
    HAVING (Relevance1+Relevance2) > 0 
    ORDER BY (Relevance1+Relevance2) DESC


回答2:

You can't match against multiple columns that aren't in the same FULLTEXT index. From http://dev.mysql.com/doc/refman/5.6/en/fulltext-restrictions.html:

The MATCH() column list must match exactly the column list in some FULLTEXT index definition for the table, unless this MATCH() is IN BOOLEAN MODE on a MyISAM table. For MyISAM tables, boolean-mode searches can be done on nonindexed columns, although they are likely to be slow.

In your particular case, you don't have an index consisting of exactly (tb1.comment, tb2.comment)—nor can you—so the match can't ever succeed.

To get this to work, create a third table linked to those tables containing the two comment fields, with both columns indexed, and perform your match against that in an apppropriate JOIN.