MySQL JOIN + WHERE没有结果

时间:2016-07-19 00:49:32

标签: mysql join where multiple-tables

我创建了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'   

这可能是愚蠢的并且没有返回任何结果。

请建议最佳实践来完成这项工作。谢谢。

1 个答案:

答案 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结构可以应用任何必要数量的标准。