【问题标题】:MySQL JOIN+WHERE gives no resultsMySQL JOIN+WHERE 没有结果
【发布时间】:2016-07-19 00:49:32
【问题描述】:

我创建了数据库(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 列是外键连接)
我需要一个带有几个可选标准的选择,这些标准返回公司所在的位置

(公司属于特定部门或部门无所谓)AND
(某些公司的关键字是“某事”或关键字无关紧要)

这是 sqlfiddle link。不幸的是有一些错误并且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 关键字='某事'。当然,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')   

它的工作方式很奇怪,因为它给出的结果都是空关键字

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'   

这可能很愚蠢并且不返回任何结果。

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

【问题讨论】:

  • 您能分享一些示例数据并 sql fiddle 吗?还要以表格形式提及您的预期输出。
  • 我在原始帖子中添加了示例表和 sqlfiddle

标签: mysql join where multiple-tables


【解决方案1】:

经过数小时的试验和研究,找到了下一个解决方案 - 我最初的意图是执行 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  

诀窍在于弄清楚当应用有效条件和省略条件 (@keyword='') 时 LEFT JOIN 结果会发生什么。在第一种情况下(@keyword''),我们需要删除所有右侧有 NULL 的行(那些不匹配的行),并由 IS NOT NULL 子句完成。
在后一种情况下,无论关键字是什么,我们都想要所有行。 WHERE TRUE 确保了这一点。 第二个 SELECT 在结构上是相同的,它只是使用部门 id 作为标准(-1 表示不关心) 使用更多的 IN 结构,可以应用任何必要数量的标准。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 2013-01-03
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多