CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Web 开发 >  PHP

数据库多对多关联问题

楼主ice_berg16(寻梦的稻草人)2006-02-16 09:58:07 在 Web 开发 / PHP 提问

三张表  
   
  表   employee     员工表  
  ---------------  
  编号       姓名  
  id           name        
  ---------------  
  表   contract     合同  
  ------------------------  
  编号       项目             签单时间         客户名称  
  id           project     signTime           customer  
  ------------------------  
  表   mapping   员工-合同映射表  
  ------------------------  
  eid           cid  
   
   
   
  员工表和合员表通过映射表关联,关系是一个员工可以签多个合同,而一个合同也可能是几个员工一起签的。就是一个多对多的关系。  
   
  目前在合同列表时出现问题。  
  在无任何查询条件下,单一列出合同列表的项目如下  
  ----------------------------------------------------------  
  客户名称               项目               签单时间                 签单人  
  CSDN                       建站             2005-03-03         小王,小张,小李  
  .....  
  这种情况可以采用如下SQL取得  
  SELECT   c.*,   e.name,   group_concat(e.name)   AS   signPerson  
  FROM   contract   AS   c  
  LEFT   JOIN   mapping   AS   m     ON   c.id=m.cid  
  LEFT   JOIN   employee   AS   e   ON   m.eid=e.id  
  GROUP   BY   c.id;  
  ----------------------------------  
  注:group_concat函数在mysql4.1以上才有效,是否有别的方法可替代  
  ----------------------------------  
  但在查询某一个员工的合同列表时就有问题  
   
  SELECT   c.*,   e.name,   group_concat(e.name)   AS   signPerson  
  FROM   contract   AS   c  
  LEFT   JOIN   mapping   AS   m     ON   c.id=m.cid  
  LEFT   JOIN   employee   AS   e   ON   m.eid=e.id  
  WHERE   m.eid   =   1  
  GROUP   BY   c.id;  
   
  ----------------------------------------------------------  
  客户名称               项目               签单时间                 签单人  
  CSDN                       建站             2005-03-03         小王  
  .......  
   
  这样会把m.eid不是1的过滤掉,在group_concat时,签单人只有一个员工,就是id=1的员工  
  目前采用的解决办法是先将mapping表中eid=1对应的合同ID取出来,  
  在执行第一条SQL,用   WHERE   c.id   IN(   ....   )来做,  
  但是IN效率不高,如果合同数据量大的话,会不会有问题?  
  -----------  
  求解决思路  
  问题点数:300、回复次数:19Top

1 楼meizz(梅花雪)回复于 2006-02-16 10:03:13 得分 30

沙发?Top

2 楼ashchen(老陳)回复于 2006-02-16 11:02:29 得分 30

板凳Top

3 楼yh801216(艾奥利斯)回复于 2006-02-16 11:10:24 得分 100

有个想法,等我测试下,  
  希望能帮到大大们。Top

4 楼eglic(圪圪) (理由永远是谎言,信仰永远是自慰)回复于 2006-02-16 11:12:15 得分 0

group_concat   是个什么函数?Top

5 楼eglic(圪圪) (理由永远是谎言,信仰永远是自慰)回复于 2006-02-16 11:15:12 得分 0

最好的办法还是,在Contract表里面加一个字段,用来记录签单人  
   
  反正一个合同签下来   签单人就定了,也不会修改  
   
  这样也就不用这么复杂了Top

6 楼yh801216(艾奥利斯)回复于 2006-02-16 11:48:49 得分 0

SELECT   c.*,   e.name,   group_concat(e.name)   AS   signPerson  
  FROM   mapping   AS   m    
  LEFT   JOIN   contract   AS   c   ON   c.id=m.cid   LEFT   JOIN   mapping   AS   m2   ON   c.id=m2.cid   LEFT   JOIN   employee   AS   e   ON   m2.eid=e.id  
  WHERE   m.eid   =   1  
  GROUP   BY   c.id;Top

7 楼yh801216(艾奥利斯)回复于 2006-02-16 11:49:30 得分 0

错了,再改改。Top

8 楼yh801216(艾奥利斯)回复于 2006-02-16 11:51:00 得分 0

SELECT   c.*,   e.name,   group_concat(e2.name)   AS   signPerson  
  FROM   mapping   AS   m    
  LEFT   JOIN   contract   AS   c   ON   c.id=m.cid   LEFT   JOIN   mapping   AS   m2   ON   c.id=m2.cid   LEFT   JOIN   employee   AS   e   ON   m.eid=e.id     LEFT   JOIN   employee   AS   e2   ON   m2.eid=e2.id   WHERE   m.eid   =   1    
  GROUP   BY   c.id;Top

9 楼helloyou0(你好!)回复于 2006-02-16 12:58:08 得分 0

来迟了~~Top

10 楼zalvsa(水米)回复于 2006-02-16 13:19:04 得分 30

这样会把m.eid不是1的过滤掉,在group_concat时,签单人只有一个员工,就是id=1的员工  
   
  你的目的不就是要把m.eid不是=1的给过滤掉吗?那过滤掉不就正好满足你的目的了?  
  Top

11 楼zalvsa(水米)回复于 2006-02-16 13:30:24 得分 0

而且好象主表的选择有问题,应该是FROM   mapping.  
  group_concat(e.name),那既然只有选择某个人,那group_concat(e.name)不就没有意义了?  
   
  select   c.*,e.name   from   mapping   as   m   left   join   employee   as   e   on   m.eid=e.id   left   join    
   
  contract   on   m.cid=c.cid   where   e.eid='1'   order   by   e.idTop

12 楼yh801216(艾奥利斯)回复于 2006-02-16 13:39:16 得分 0

查询结果explain后的结果是   查询员工   所签的每个合同包含的员工数的总和。  
  效率应该可以。  
  楼主看下:P  
   
   
  另外,group_concat的替代方法在mysql中可能很难找。。  
  只能不group   by   而用order   by   ,然后在程序里组合字符串。。。  
   
  SELECT   c.*,   e.name,   e2.name   FROM   mapping   AS   m    
  LEFT   JOIN   contract   AS   c   ON   c.id=m.cid   LEFT   JOIN   mapping   AS   m2   ON   c.id=m2.cid   LEFT   JOIN   employee   AS   e   ON   m.eid=e.id     LEFT   JOIN   employee   AS   e2   ON   m2.eid=e2.id   WHERE   m.eid   =   1    
  ORDER   BY   c.id;  
   
   
  仅仅是我能想到的哈。:P  
  Top

13 楼ice_berg16(寻梦的稻草人)回复于 2006-02-16 15:04:37 得分 0

to     zalvsa(水米)  
  我的目的是得到该员工的合同列表,如果一个合同有二个以上的签单人,  
  那么m.eid!=1的人员就被过滤了,也就是说本来这个人也有签单的份,列表中的签单人却没人他,举个例子  
  ----mapping表----  
  eid           cid  
    1               1  
    2               1  
    2               2  
    1               3  
  ----employee表----  
  id             name  
  1               小王  
  2               小李  
  ----contract表----  
  id             project           signTime           customer  
  1                   建站               2005-11-29           CSDN  
  2                   推广               2006-01-02           CSDN  
  3                   Google           2006-02-13           CSDN  
  -----------------------  
  不指定条件的结果应该是这样  
   
  客户名称               项目               签单时间                 签单人  
  CSDN                       建站             2005-03-03             小王,小李  
  CSDN                       推广             2006-01-02             小李  
  CSDN                       Google         2006-02-13             小王  
  ------------------------  
  指定条件后(假如查eid=1的,即小王)  
   
  客户名称               项目               签单时间                 签单人  
  CSDN                       建站             2005-03-03             小王  
  CSDN                       Google         2006-02-13             小王  
   
  可以看到本来小李也参与了建站的项目,却没显示出来,  
  因为where   m.eid=1的时候把m表中的   eid=2     cid=1这条记录过滤了,  
  group_concat的时候无论什么合同都只有变成只有小王一人了,  
  这就是问题。Top

14 楼ice_berg16(寻梦的稻草人)回复于 2006-02-16 15:05:47 得分 0

to     yh801216(艾奥利斯)    
   
  由员签单人的个数不是固定的,  
  仅通过join多个m和e表是不能解决所有问题的。Top

15 楼yh801216(艾奥利斯)回复于 2006-02-16 16:26:11 得分 0

...  
  楼主仔细看看嘛。。。  
   
  小子再菜,你也该仔细看看再评价吧。。。Top

16 楼zalvsa(水米)回复于 2006-02-16 16:33:30 得分 0

明白LZ的意思了,是如果合同有A,则这个合同的所有人员都要列出来,而不是只列A。  
  那这样的话,估计只有通过PHP来实现了。group_concat没办法拿来做条件判断。Top

17 楼Cain(一苇渡江)回复于 2006-02-16 16:40:44 得分 40

留个记号,一会回来再看Top

18 楼yh801216(艾奥利斯)回复于 2006-02-16 17:20:08 得分 30

。。。  
  这都哪是哪啊。。。。  
  我闪了。  
   
  楼主试验一下我的行不行吧,我想能够满足你的要求。  
   
  你们继续:PTop

19 楼helloyou0(你好!)回复于 2006-02-17 12:50:59 得分 40

笑坏了,小艾的明明是对的,就是无处伸冤~~~~~~  
   
  那个sql里包括了第一个sql,然后再做一个自连接到employee表  
   
  Top

相关问题

  • 一对多关联的数据库在VB.NET中如何新增记录
  • 多级部门,Treeview控件与数据库关联
  • 有关数据库关联
  • 一对多数据库设计
  • 如何对两个服务器上的数据库进行关联查询
  • 再次请教VB数据库关联
  • 什么叫关联数据库? 增分
  • 请教svg数据库关联问题!
  • 数据库动态关联的问题
  • 数据库关联问题,在线等

关键词

  • 员工
  • csdn
  • 项目
  • 客户
  • 查询
  • eid
  • 签单
  • 合同
  • concat
  • cid

得分解答快速导航

  • 帖主:ice_berg16
  • meizz
  • ashchen
  • yh801216
  • zalvsa
  • Cain
  • yh801216
  • helloyou0

相关链接

  • Web开发类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo