Mysql - 搜索多个表

时间:2015-05-25 12:40:28

标签: mysql left-join union

我想对多个表执行简单搜索 并接收搜索命中和一些其他信息

我的数据库架构

  • table1:| id | entry1 | entry2 | entry3 |
  • table2:| id | entry1 | entry2 | entry3 |
  • table3:| id | entry1 | entry2 | entry3 |
  • table4:| id | entry1 | entry2 | entry3 |
  • table5:| id | entry1 | entry2 | entry3 |

(ID列是不同表的外键,条目是varchars)

让我们说table1包含(1,' abc',' def',' ghi')

和table2包含(1,' test',''''')

使用' test'进行搜索应该返回类似的东西 '测试'' ABC'' DEF'' GHI'

选项1:

加入所有表并选择正确的行

Select * from
   big_Table_with_all_ID as t0
   /* mysql does not support FULL JOIN. we avoid this with LEFT-JOINS on 
   a table containing all IDs. Not exactly the same */
left join
   table1 as t1
on t0.id = t1.id

left join
   table2 as t2
on t0.id = t2.id
[...]
left join
   table5 as t5
on t0.id = t5.id

where t1.entry1 like '%search%' or 
      t1.entry2 like '%search%' or
      [...]
      t5.entry3 like '%search%'

这不会标记'搜索命中(可由客户完成) 应该是最糟糕的选择,因为加入了太多的数据,包括 输出中的大量信息

选项2:添加子查询

加入'过滤'表

Select * from
   big_Table_with_all_ID as t0
left join
   (Select id,entry1 from table1 where entry1 like '%search%') as t1
on t0.id = t1.id

left join
   (Select id,entry2 from table1 where entry2 like '%search%') as t2
on t0.id = t2.id
[...]
left join
   (Select id,entry3 from table5 where entry3 like '%search%') as t15
on t0.id = t15.id

left join
   table1
on t0.id = table1.id;

输出:

ID|table1        |table2          |...|table1           |
1 |NULL|NULL|NULL|'test'|NULL|NULL|...|'abc'|'dfg'|'ghi'|
即使没有搜索命中,

也会包含每个ID(仅限NULL值) (可以通过从option1添加where子句来解决)

选项3:UNION

UNION'过滤'表和加入其他数据

Select hit,entry1,entry2,entry3 from
(
   Select * from
      (
         Select id,entry1 as hit from table1 where entry1 like '%search%'
         UNION
         Select id,entry2 as hit from table1 where entry2 like '%search%'
         [...]
         UNION
         Select id,entry3 as hit from table5 where entry3 like '%search%'
      ) as tmp
      group by id  
) as tmp
left join
   table1
on tmp.id = table1.id
where hit is not null

输出:

hit   |entry1|entry2|entry3
'test'|'abc' |'def' |'ghi'

不包含不必要的信息

我应该选择哪种选择/替代方案,以获得“好”的选择。性能 和可读性?

2 个答案:

答案 0 :(得分:0)

选项1不好,因为mysql可能会出现连接多个表的问题,我不会使用它。考虑到子查询的结果很小(只有1行)的事实,我认为选项2和3是相似的。

答案 1 :(得分:0)

我认为您想在第三种方法中使用变体:

Select t1.*, entry1, entry2, entry3
from (Select id, max(entry1) as entry1,
             max(entry2) as entry2, max(entry3) as entry3
     from (Select id, entry1 as hit, NULL as entry2, NULL as entry3 from table1 where entry1 like '%search%'
           UNION ALL
           Select id, NULL, entry2 as hit, NULL from table2 where entry2 like '%search%'
           [...]
           UNION ALL
           Select id, NULL, NULL, entry3 as hit from table5 where entry3 like '%search%'
          ) as tmp
     group py id  
    ) as tmp join
    table1 t1
    on tmp.id = t1.id;

一些意见:

  • 您希望使用union all而不是union来避免不必要的重复消除。
  • 请勿将select *group by一起使用。结果是不确定的。
  • 虽然在这种情况下并不重要(因为like在开头有一个通配符),但如果合适,单独的查询可以各自利用索引。
  • 我不理解三个条目和五个表之间的映射,但此查询遵循您的结构。
  • 我不知道hit is not null应该做什么。我认为join捕获了正确的逻辑。