我正在使用SQL进行一个简单的搜索功能,但卡住了。我使用 GROUP_CONCAT 将所有关键字放在一行中。关键字取自类别。
并非所有列都在此示例中。我已经把它剥离了
SELECT
p.id as id,
p.title as title,
p.title as company,
GROUP_CONCAT(DISTINCT cat.title SEPARATOR " ") as keywords,
FROM products p
JOIN product_categories pc ON p.id = pc.product_id
JOIN categories cat ON pc.category_id = cat.id
JOIN companies co ON p.company_id = co.id
WHERE MATCH (p.title) AGAINST ("Test")
OR MATCH (co.title) AGAINST ("Test")
GROUP BY p.id
keywords
包含类似 keyword1 keyword2 keyword3
.
上面的 SQL 正在工作。但是,我不能将 MATCH AGAINST 与虚拟值keywords
值一起使用。
我已经阅读了我认为是一种丑陋的解决方法,以添加以下内容:
HAVING keywords LIKE "%keyword1%"
LIKE 可能很慢,因为 HAVING 是在 GROUP BY 之后,我不能使用 OR 所以在这种情况下 HAVING 会覆盖 WHERE。
理想情况下,我也想在keywords
上使用 MATCH AGAINST 。那么,我有哪些选择呢?
- 某种虚拟表?
- 子查询?
- 别的?
我可能需要一个示例代码来理解。
这并不能回答您提出的问题,但我认为将此条件添加到查询的 WHERE 子句中:
OR EXISTS ( SELECT 1
FROM categories k
WHERE k.id = pc.category_id
AND k.title IN ('Test1','Test2')
)
如果规范是返回类别标题与指定搜索词之一匹配的行,则GROUP BY
将消除从GROUP_CONCAT
扫描返回的需要。
如果不需要在结果集中实际返回派生的keywords
列,我会避免使用 GROUP BY。
SELECT p.id AS id
, p.title AS title
, p.title AS company
FROM products p
JOIN companies co
ON co.id = p.company_id
WHERE MATCH (p.title) AGAINST ('Test')
OR MATCH (co.title) AGAINST ('Test')
OR EXISTS ( SELECT 1
FROM categories k
JOIN product_categories pc
ON pc.category_id = k.id
WHERE pc.product_id = p.id
AND k.title IN ('Test1','Test2')
)
ORDER BY p.id