我创建了DB(MySQL 5.5,Ubuntu 14.04),我希望按部门(该公司所属)和关键字搜索公司。假设我们有表格 -
company (c_id,c_name)
-------------------------------
1 'A-Z hair'
2 'My Coffee'
3 'Boom Disco'
4 'Go Cinema'
keywords (c_fk , keyword)
-----------------
1 'haircut'
1 'pruning'
1 'coloring'
2 'coffee'
2 'tea'
2 'free wifi'
division( d_id , d_name)
---------------
1 'shop'
2 'service'
3 'manufacturing'
4 'engineering'
5 'food'
6 'entertainment'
comp_div ( c_fk , d_fk )
-----------------------
1 2
2 5
2 2
4 6
(.._ fk列是外键连接)
我需要一个带有几个可选标准的选择,返回公司
(公司属于特定部门OR部门无关紧要)和
(某些公司的关键字是“某事物”或“关键字无关紧要”)
这是sqlfiddle link。不幸的是有一些bug并且Mysql 5.5模式不起作用,所以我在5.6上测试
我开始编译我的搜索查询并创建以下JOIN
SELECT c_id,c_name,d_fk,keyword FROM company
LEFT JOIN comp_div ON c_id=comp_div.c_fk
LEFT JOIN keywords ON c_id=keywords.c_fk
按预期工作,并为所有公司*行*关键字
提供所有行然后我想用额外的WHERE来优化结果,所以我添加例如 WHERE keyword ='something'。当然,NULL比较存在问题,因此WHERE失败并且查询没有给出结果。对于存在关键字和/或除法参数但也不存在的情况,我打算扩展搜索请求。所以我的想法就是拥有这样的东西 -
SELECT c_id,c_name,d_fk,keyword FROM company
LEFT JOIN comp_div ON c_id=comp_div.c_fk
LEFT JOIN keywords ON c_id=keywords.c_fk
WHERE (''=keyword OR keyword LIKE somethin%) AND
(comp_div.d_fk=<division_fk> OR comp_div.d_fk = 0)
我拼命尝试所有方法,例如
1.移动条件为ON ..
SELECT c_id,c_name,d_fk,keyword FROM company
LEFT JOIN comp_div ON c_id=comp_div.c_fk
LEFT JOIN keywords ON (c_id=keywords.c_fk) AND (keyword='something')
以奇怪的方式工作,因为它使用null关键字
给出结果2.在没有WHERE + IFNULL / COALESCE的情况下在派生表上应用WHERE
SELECT c_id,c_name,d_fk,keyword FROM(
SELECT c_id,c_name,d_fk,keyword FROM company
LEFT JOIN comp_div ON c_id=comp_div.c_fk
LEFT JOIN keywords ON c_id=keywords.c_fk) dt
WHERE COALESCE(dt.keyword,'')='something'
这可能是愚蠢的并且没有返回任何结果。
请建议最佳实践来完成这项工作。谢谢。
答案 0 :(得分:0)
经过一小时的试验和研究,找到了下一个解决方案 - 我最初的目的是执行2个选择,每个标准一个(除法,关键字),然后进行表格交叉。由于MySQL不支持INTERSECT,因此可以通过IN运算符和子查询进行模拟,如此处 -
SELECT c_id,c_name FROM company
LEFT JOIN keywords K ON c_id=K.c_fk AND K.keyword LIKE @keyword
WHERE (K.c_fk IS NOT NULL OR @keyword='') AND
c_id IN (
SELECT c_id FROM company
LEFT JOIN comp_div D ON c_id=D.c_fk AND D.d_fk = @division
WHERE D.c_fk IS NOT NULL OR @division=-1)
GROUP BY c_id
当应用有效标准并且省略标准时,诀窍在于弄清楚LEFT JOIN结果会发生什么(@keyword =&#39;&#39;)。在第一种情况下(@ keyword&lt;&gt;&#39;&#39;)我们需要删除所有在右侧具有NULL的行(不匹配的行)和由IS NOT NULL子句完成的行。
在后一种情况下,无论关键字是什么,我们都需要所有行。这是由WHERE TRUE确保的。
第二个SELECT在结构上是相同的,它只使用分区ID作为标准(-1表示不小心)
使用更多IN结构可以应用任何必要数量的标准。