我正在尝试更改Wordpress搜索查询,以便返回更广泛的结果。
情景:
数据库中有一个帖子条目标题“Carousel Watch”。当我搜索这些单词中的任何一个(或两个单词)时,我会收到帖子,这是我期望的。
但是,如果我搜索“Carousel Watch Gift”,我不会得到任何结果。
此搜索的SQL查询如下:
SELECT SQL_CALC_FOUND_ROWS sosen_posts.ID FROM sosen_posts WHERE 1=1
AND (((sosen_posts.post_title LIKE '%carousel%') OR (sosen_posts.post_content LIKE '%carousel%'))
AND ((sosen_posts.post_title LIKE '%watch%') OR (sosen_posts.post_content LIKE '%watch%'))
AND ((sosen_posts.post_title LIKE '%gift%') OR (sosen_posts.post_content LIKE '%gift%')))
AND (sosen_posts.post_password = '') AND sosen_posts.post_type = 'wp_aff_products' AND (sosen_posts.post_status = 'publish')
ORDER BY
(CASE WHEN sosen_posts.post_title LIKE '%carousel watch gift%'
THEN 1
WHEN sosen_posts.post_title LIKE '%carousel%' AND sosen_posts.post_title LIKE '%watch%' AND sosen_posts.post_title LIKE '%gift%'
THEN 2
WHEN sosen_posts.post_title LIKE '%carousel%' OR sosen_posts.post_title LIKE '%watch%' OR sosen_posts.post_title LIKE '%gift%'
THEN 3
WHEN sosen_posts.post_content LIKE '%carousel watch gift%'
THEN 4 ELSE 5 END), sosen_posts.post_date DESC LIMIT 0, 3
我的问题是:
THEN
语句在此查询中的作用是什么?它是否在WHERE
语句中设置要比较的值?答案 0 :(得分:2)
THEN
关键字用作CASE
子句的一部分。 CASE
子句如下所示:
CASE WHEN expression THEN value WHEN otherexpression THEN othervalue ... END
表达式的结果是单个值(有时您会看到人们尝试使用CASE
子句来确定将执行哪些代码,这不会起作用) 。
在此查询中,CASE
条款中的值用于确定帖子的排序顺序,并且与结果中包含或未包含的记录无关。
要找出结果中包含哪些记录,我们需要剖析WHERE
子句。我重新格式化了现有条款,以便于阅读:
WHERE 1=1 AND (
(sosen_posts.post_title LIKE '%carousel%' OR sosen_posts.post_content LIKE '%carousel%')
AND (sosen_posts.post_title LIKE '%watch%' OR sosen_posts.post_content LIKE '%watch%')
AND (sosen_posts.post_title LIKE '%gift%' OR sosen_posts.post_content LIKE '%gift%')
) AND sosen_posts.post_password = '' AND sosen_posts.post_type = 'wp_aff_products' AND sosen_posts.post_status = 'publish'
首先,1 = 1部分。这对于自动生成的代码很常见。无论是否有任何条件,生成器都可以在WHERE 1=1
子句的开头放置WHERE
,查询仍然有效。然后,对于每个条件,它总是可以使用AND condition
形式,而不必担心WHERE子句的先前状态。
进入下一部分,我们看到它会针对标题和文本单独检查每个关键字。这些检查通过AND
运营商连接。这意味着,如果您的帖子在标题或正文某处中没有单词gift
,则它不会出现在结果中。
最后,这段代码非常低效。您从不想要使用前导通配符(LIKE
)查看%
运算符,因为它几乎可以保证您无法使用任何索引来满足该条件。我更多的是一个Sql Server人,但是在Sql Server -land中你要做的是创建一种特殊的索引,称为full text
索引,并使用特殊的{{来编写查询1}}子句。如果做不到这一点,您可以使用第三方搜索库,例如Lucene。您从不想要对此类搜索使用CONTAINS()
次查询。我不确定这些替代品的MySql等价物是什么,但你在这里所拥有的是 not 你想要这样做的方式。
答案 1 :(得分:1)
希望这有帮助。
答案 2 :(得分:0)
为您的查询提供更好的格式(见下文),结果是在where子句中过滤了标题或内容中包含轮播的行,请观看 AND 礼物。
case语句只会改变结果的顺序,但是如果用这三个单词构建查询,它将获取包含所有这些单词的行。
SELECT SQL_CALC_FOUND_ROWS sosen_posts.ID FROM sosen_posts
WHERE 1=1
AND (((sosen_posts.post_title LIKE '%carousel%')
OR (sosen_posts.post_content LIKE '%carousel%')
)
AND ((sosen_posts.post_title LIKE '%watch%')
OR (sosen_posts.post_content LIKE '%watch%')
)
AND ((sosen_posts.post_title LIKE '%gift%')
OR (sosen_posts.post_content LIKE '%gift%')
)
)
AND (sosen_posts.post_password = '')
AND sosen_posts.post_type = 'wp_aff_products'
AND (sosen_posts.post_status = 'publish')
ORDER BY (CASE WHEN sosen_posts.post_title LIKE '%carousel watch gift%' THEN 1
WHEN sosen_posts.post_title LIKE '%carousel%' AND sosen_posts.post_title LIKE '%watch%' AND sosen_posts.post_title LIKE '%gift%' THEN 2
WHEN sosen_posts.post_title LIKE '%carousel%' OR sosen_posts.post_title LIKE '%watch%' OR sosen_posts.post_title LIKE '%gift%' THEN 3
WHEN sosen_posts.post_content LIKE '%carousel watch gift%' THEN 4
ELSE 5
END),
sosen_posts.post_date DESC
LIMIT 0, 3
另请注意,LIMIT 0将返回空集。