我有以下查询,用于自动填写用户正在搜索的学校名称。如果$query = har
SELECT *,
CASE
WHEN text LIKE '$query' THEN 1
WHEN text LIKE '$query%' THEN 2
WHEN text LIKE '%$query%' THEN 3
end AS priority
FROM (SELECT b.school_name AS `text`,
'school' AS `type`,
b.slug AS `id`,
n.neighbourhood AS 'params'
FROM schools b
LEFT JOIN school_addresses ba
ON ( b.id = ba.school_id )
LEFT JOIN neighbourhoods n
ON ( ba.neighbourhood_id = n.id )
WHERE b.entity_status = 'active'
AND ba.city_id = '$city'
AND b.visibility != 'delisted'
AND (b.school_name LIKE '$query'
OR b.school_name LIKE '$query%'
OR b.school_name LIKE '%$query%')
UNION
SELECT tg.OPTION AS `text`,
'tags' AS `type`,
tg.OPTION AS `id`,
tg.OPTION AS 'params'
FROM tags t
LEFT JOIN tag_options tg
ON ( t.id = tg.tag_id )
WHERE t.tag = 'Cuisines'
AND (tg.OPTION LIKE '$query'
OR tg.OPTION LIKE '$query%'
OR tg.OPTION LIKE '%$query%')
UNION
SELECT category AS `text`,
'category' AS `type`,
category AS `id`,
category AS 'params'
FROM categories
WHERE category LIKE '$query'
OR category LIKE '$query%'
OR category LIKE '%$query%'
UNION
SELECT area AS `text`,
'area' AS `type`,
id AS `id`,
id AS 'params'
FROM areas
WHERE city_id = '$city'
AND (area LIKE '$query'
OR area LIKE '$query%'
OR area LIKE '%$query%')
UNION
SELECT district AS `text`,
'districts' AS `type`,
id AS `id`,
id AS 'params'
FROM districts
WHERE city_id = '$city'
AND (district LIKE '$query'
OR district LIKE '$query%'
OR district LIKE '%$query%')
UNION
SELECT neighbourhood AS `text`,
'neighbourhood' AS `type`,
id AS `id`,
id AS 'params'
FROM neighbourhoods
WHERE city_id = '$city'
AND (neighbourhood LIKE '$query'
OR neighbourhood LIKE '$query%'
OR neighbourhood LIKE '%$query%')
) AS t1
WHERE 1
ORDER BY priority
LIMIT 5
这是它产生的结果
'text' 'type' 'id' 'params' 'priority'
Harvard mba harv-ny-city new york 2
Harcum mba har-pa Pa 2
Harford mba harf-md Maryland 2
我的问题是如何使用上述查询中的“学校名称”“文本”和上述查询中的“学校名称”'params'进行搜索。喜欢如果$ query ='harford ma' 然后它应该产生这样的结果:
'text' 'type' 'id' 'params' 'priority'
Harford mba harf-md Maryland 2
Harford mba harv-ny-city new york 2
Harford mba har-pa Pa 2
我几乎整天都玩这个,没有结果。
逻辑 - >这是我网站中的自动搜索功能。用户可以尝试查找这些学校的学校名称或城市。但是用户也可以同时搜索。例如,在孟买,德里,钦奈有学校iit。用户可以搜索:“iit de” - >一旦用户键入它,它应该自动完成并在顶部搜索引入iit Delhi,然后在其他iit位置引入。总共它应该显示5个结果。
答案 0 :(得分:1)
通常,您必须使用您用来调用此查询的任何编程语言来处理此问题。
您需要将查询拆分为单独的单词,并对其进行清理(以防止SQL注入,并删除可能影响“喜欢”查询的%
个字符。如果不这样做,请删除标点符号把它放在实际的表中会很好地做到这一点。)
然后,您必须动态构建查询,并在每个字段中将每个单词用作查询字词,例如:
AND (b.school_name LIKE '%$queryWords[0]%'
OR b.school_name LIKE '%$queryWords[1]%'
OR b.school_name LIKE '%$queryWords[2]%')
......等等。
请务必注意,WHERE
中的条件不需要LIKE 'x%' OR LIKE '%x' OR like '%x%'
。这是多余的,并且会不必要地减慢查询速度,因为所有查询都包含在LIKE '%x%'
中。如果匹配是否完全匹配,那么唯一可以产生差异的地方就是在你构造优先顺序的表达式中,所以每个where条件应该如我在上面所指出的那样 - 只需LIKE '%$word%'
单词。
或者您可以决定对于学校名称,您只测试$word[0]
,对于学校名称,您只需选中$word[1]
或者等等。这取决于您是否认为人们会输入ma harford
或harford ma
等查询。
这里面临的最大挑战是构建优先级。我建议优先级越高,数字越高,而不是越低,因为这将允许您对给定字段求和优先级。因此,请使用ORDER BY priority DESC
。
优先表达本身会相当复杂:
CASE WHEN text = '$queryWords[0]' OR text = '$queryWords[1]' THEN 3
WHEN text LIKE '$queryWords[0]%' OR text LIKE '$queryWords[1]%' THEN 2
WHEN text LIKE '%$queryWords[0]%' OR text LIKE '%$queryWords[1]%' THEN 1
ELSE 0
END
+
CASE WHEN params = '$queryWords[0]' OR params = '$queryWords[1]' THEN 3
WHEN params LIKE '$queryWords[0]%' OR params LIKE '$queryWords[1]%' THEN 2
WHEN params LIKE '%$queryWords[0]%' OR params LIKE '%$queryWords[1]%' THEN 1
ELSE 0
END
AS priority
(当然,如果有更多字词,则每个OR
中会有更长的WHEN
部分。
如果你想给学校名称增加权重而不是给学校的地方,那么你应该把它改成:
CASE WHEN text = '$queryWords[0]' OR text = '$queryWords[1]' THEN 12
WHEN text LIKE '$queryWords[0]%' OR text LIKE '$queryWords[1]%' THEN 8
WHEN text LIKE '%$queryWords[0]%' OR text LIKE '%$queryWords[1]%' THEN 4
ELSE 0
END
+
CASE WHEN params = '$queryWords[0]' OR params = '$queryWords[1]' THEN 3
WHEN params LIKE '$queryWords[0]%' OR params LIKE '$queryWords[1]%' THEN 2
WHEN params LIKE '%$queryWords[0]%' OR params LIKE '%$queryWords[1]%' THEN 1
ELSE 0
END
AS priority
这基本上将优先级建立为基数为4的数字,因此text
上的匹配,即使是最不精确的选项,也始终高于params
上的匹配,即使在最佳匹配中也是如此。如果添加另一个匹配条件,则将每个数字乘以4,并在结尾处添加3,2,1。