Mysql多对多查询、列合并

[b][size=medium]表信息[/size][/b]
[list]
[*]资源表 synsource [b]199824[/b] rows
[*]产品表 tab_product_detail [b]108[/b] rows
[*]资源与产品多对多的关联表 tab_r_sourmach [b]1,113,866[/b] rows
[/list][i]以上表均采用MyISAM引擎.[/i]

[b][size=medium]连接测试[/size][/b]
因 为方便用户进行更好的资源的搜索,所以需要将资源数据全部建立索引至Lucene中,希望在Lucene中存储的Document为:
[table]
|sourceName|fileName|subject|grade|products|
|英语学生用书第十一册|外研新标准.nwe|英语|小学|NP7000 NP6000 NP2300|
|英语学生用书第十二册|外研新标准2.nwe|英语|小学|NP2300|
[/table]
以上前四个字段是属于 synsource表中,而 products 属于 tab_product_detail 表,它们之间的关系由tab_r_sourmach进行中间关联。
一开始想到的是直接使用以下SQL:

select s1.sourid, s1.sourcename , t.product_name from synsource s1
left join tab_r_sourmach c
on s1.sourid=c.sourid
left join tab_product_detail t
on c.product_id = t.product_id where s1.sourceid=1

[table]
| sourid | sourcename | subjectname | product_name |
| 1 | 小六上Module07 | 英语 | ND520 |
| 1 | 小六上Module07 | 英语 | NP560T |
| 1 | 小六上Module07 | 英语 | NP560+ |
| 1 | 小六上Module07 | 英语 | NP360+ |
5 rows in set (0.45 sec)
[/table]
对于以上SQL的结果重复数据的合并处理考虑采用了 [b]GROUP_CONCAT[/b]:
select s1.*, GROUP_CONCAT(t.product_name SEPARATOR ' ') as product_name
from tab_synsource s1
left join tab_r_sourmach c
on s1.sourid=c.sourid
left join tab_product_detail t
on c.product_id = t.product_id where s1.sourceid=1

[table]
|sourid | sourcename | subjectname | product_name |
|1 | 小六上Module07 | 英语 | ND520 NTV518 NP560T NP560+ NP360+ |
1 row in set (0.31 sec)
[/table]
看上去似乎能够满足需求,但是以上只是针对单条数据进行查询,对于数据的批量索引建立的话肯定是直接 limit 500之类的操作。于是去掉以上where加上 limit 10执行之后,半天都执行不出来,估计它先会全部数据连接查询之后再去 limit。
于是先测试一下直接(tab_r_sourmach, tab_product_detail)两表关联看看效率如何:
select c.sourid
from tab_r_sourmach c left join tab_product_detail t
on c.product_id = t.product_id
group by c.sourid limit 500;

以上语句用时:(5.65 sec)

再加上GROUP_CONCAT试试:
select c.sourid, GROUP_CONCAT(t.product_name SEPARATOR ' ') as products
from tab_r_sourmach c left join tab_product_detail t
on c.product_id = t.product_id
group by c.sourid limit 800;

输出结果样例:
[table]
| sourid | products|
| 767 | ND520 ND416 NTV518 NP560T NP560+ NP360+|
| 760 | ND550 NP600+ NP9588 NP600
[/table]
800 rows in set (1.74 sec) , 经过反复测试都发现加上了GROUP_CONCAT 函数比没使用该函数快了五倍多,暂时还不知道为什么。
不过1秒左右对于后台索引建立来说还算能够接受,于是再将以上SQL与 synsource 进行连接测试:

select * from synsource s, (
select c.sourid,
GROUP_CONCAT(t.product_name SEPARATOR ' ')
from tab_r_sourmach c left join tab_product_detail t
on
c.product_id = t.product_id
group by c.sourid limit 1000
) as b
where s.sourid = b.sourid;

输出结果样例:
[table]
| 968 | 词汇学习-第三级K(参考剑桥少儿英语) | 英语 | NP600+ NP600 |
| 983 | 词汇学习-六年级上Unit7(参考湘教版) | 英语 | ND520 ND416 NTV518 NP560T NP560+ NP360+
[/table]
1000 rows in set (2.02 sec)


[b]不知道大家对这种情况如何处理的?以上的SQL虽然能够达到目的,不过还是存在不足。[/b]

[i]忘说了,在使用MYSQL GROUP_CONCAT函数进行分组连接时,它对字符串的长度连接是有长度限止的,默认的情况的话我发布 products 太长的话会被截断,如果想一劳永逸的话直接在my.cnf 中加入 group_concat_max_len=99999 即可。[/i]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值