mysql左边连接9个表

时间:2013-02-17 17:14:58

标签: php mysql

所以情况是我有一个涉及9个表的查询,我需要编写它,这样即使impactid表中的workorderstatesNULL,它也会返回所有记录。 / p>

在下面的查询之前,我注意到我没有得到所有“开放”的结果,因为最初我只有workorderstates.impactid = impactdefiniton.impactid,而impactidNULL的情况workorderstates表这个条件不成立,因此消除了应该返回的记录,因为它们实际上是“开放的”。

所以我在下面设计了这个查询,但每次运行它都不行。它将不会返回唯一的表别名workorder。如果我对表使用别名,它只是在连接中的右表上移动而不是唯一的。任何人都可以给我任何帮助重组查询,以便它可以工作吗?我已经尝试了很多变化,有趣的是第二个查询ALMOST工作但是它返回重复记录(在这种情况下是同一记录中的四个)

select workorder.workorderid, workorder.siteid, 
 FROM_UNIXTIME(workorder.CREATEDTIME/1000, '%m-%d-%Y %H:%i:%s') as createdate, 
 categoryname, IFNULL(workorderstates.impactid, "No Set") as impactid, 
 IFNULL(impactdefinition.name, "Not Set") as impactname, first_name,
 sdorganization.name, statusname, title 
from workorder,  statusdefinition, sitedefinition, sdorganization, 
 prioritydefinition, categorydefinition, sduser, aaauser, workorderstates 
left Join impactdefinition on workorderstates.impactid = impactdefinition.impactid  
left join workorder on workorder.workorderid = workorderstates.workorderid 
left join workorderstates on workorderstates.statusid = statusdefinition.statusid 
left join workorder on workorder.siteid = sitedefinition.siteid 
left join sitedefinition on sitedefinition.siteid = sdorganization.org_id  
left join workorderstates on workorderstates.categoryid = categorydefinition.categoryid
left join workorder on workorder.requesterid = sduser.userid 
left join sduser on sduser.userid = aaauser.user_id  
where statusname='Open' and workorder.createdtime >= '1352678400000' 
 and sdorganization.name='MAPL' 
order by workorder.workorderid

查询几乎可行,但很难看(返回重复的记录):

select workorder.workorderid, workorder.siteid, 
 FROM_UNIXTIME(workorder.CREATEDTIME/1000, '%m-%d-%Y %H:%i:%s') as createdate,  
 categoryname, IFNULL(workorderstates.impactid, "No Set") as impactid, 
 IFNULL(impactdefinition.name, "Not Set") as impactname, first_name, 
 sdorganization.name, statusname, title 
from workorder,  statusdefinition, sitedefinition, sdorganization, 
 prioritydefinition, categorydefinition, sduser, aaauser, workorderstates 
left Join impactdefinition on workorderstates.impactid = impactdefinition.impactid 
where workorder.workorderid = workorderstates.workorderid 
 and workorderstates.statusid = statusdefinition.statusid 
 and workorder.siteid = sitedefinition.siteid 
 and sitedefinition.siteid = sdorganization.org_id 
 and workorderstates.categoryid = categorydefinition.categoryid 
 and  workorder.requesterid = sduser.userid and sduser.userid = aaauser.user_id 
 and statusname='Open' and workorder.createdtime >= '1352678400000' 
and sdorganization.name='MAPL' 
order by workorder.workorderid

如何使这个查询工作的任何想法?谢谢你们!

2 个答案:

答案 0 :(得分:1)

我查看了您的查询,我认为您对JOIN以及如何编写它们有一些基本的误解。就像你只是随意猜测语法一样,这不是编写代码的方法。

我检查了你的查询并将其转换为SQL-92语法。我不得不对连接条件做出一些推论,所以我无法保证它对你的应用程序是正确的,但它更接近于合法查询。

只有我在您的示例中找不到加入prioritydefinition表的任何条件。这可能是您重复行的原因。你正在生成所谓的Cartesian product

select workorder.workorderid, workorder.siteid, 
 FROM_UNIXTIME(workorder.CREATEDTIME/1000, '%m-%d-%Y %H:%i:%s') as createdate, 
 categoryname, IFNULL(workorderstates.impactid, "No Set") as impactid, 
 IFNULL(impactdefinition.name, "Not Set") as impactname, first_name,
 sdorganization.name, statusname, title 
from workorder
inner join statusdefinition on workorderstates.statusid = statusdefinition.statusid
inner join sitedefinition on workorder.siteid = sitedefinition.siteid
inner join sdorganization on sitedefinition.siteid = sdorganization.org_id
inner join prioritydefinition ...NO JOIN CONDITION FOUND...
inner join categorydefinition on workorderstates.categoryid = categorydefinition.categoryid
inner join sduser on workorder.requesterid = sduser.userid
inner join aaauser on sduser.userid = aaauser.user_id
inner join workorderstates on workorder.workorderid = workorderstates.workorderid
left Join impactdefinition on workorderstates.impactid = impactdefinition.impactid  
where statusname='Open' 
 and workorder.createdtime >= '1352678400000' 
 and sdorganization.name='MAPL' 
order by workorder.workorderid

你真的需要找一个知道你的应用程序的人,并且在你再编写SQL连接之前也知道如何编写SQL来辅导你。

答案 1 :(得分:0)

我也重新格式化了你的查询,但是它具有更直观的层次结构,以显示从第一个(左侧)表到从(右侧)表获取其详细信息的关系。正如比尔提到的那样,你有一张额外的桌子没有做任何事情,因而也就是你的笛卡尔产品。

现在,如果你被困住并没有其他人真正帮助,这里是LEFT-JOIN和INNER-JOIN的基础。左连接基本上说我希望左边的表中的每条记录(正如我先列出的那样),但是在右侧找到了记录。如果匹配,很好,没问题......但如果不匹配,您的查询仍会运行。

所以,我已经设置了所有LEFT-JOIN。您可以根据需要更改您知道必须始终存在的人...例如工作订单由“用户”输入。这样你就可以改变。希望这会帮助你。另请参阅我如何从工作订单嵌套到工作订单状态和工作订单状态,以获取相应的状态定义以及与工作订单状态表关联的其他内容。其他人与工作单直接相关,因此处于等级水平。

最后一个注意事项......并非所有字段都是table.field引用(我将其更改为别名以帮助提高可读性)。合法所有字段,以便您和其他人尝试提供帮助,或者将来阅读您的代码知道该字段的来源,而不仅仅是猜测(在其中一个表中)

select 
      WO.workorderid, 
      WO.siteid, 
      FROM_UNIXTIME(WO.CREATEDTIME/1000, '%m-%d-%Y %H:%i:%s') as createdate,  
      categoryname, 
      IFNULL(WOS.impactid, "No Set") as impactid, 
      IFNULL(ImpD.name, "Not Set") as impactname, first_name, 
      SDO.name, 
      statusname, 
      title 
   from 
      workorder WO
         LEFT JOIN workorderstates WOS
            ON WO.workorderid = WOS.workorderid 

            LEFT JOIN statusdefinition StatD
               ON WOS.statusid = StatD.statusid 

            LEFT JOIN categorydefinition CatD
               ON WOS.categoryid = CatD.categoryid 

            LEFT JOIN impactdefinition ImpD
               ON WOS.impactid = ImpD.impactid 

         LEFT JOIN sitedefinition SiteD
            ON WO.siteid = SiteD.siteid 

            LEFT JOIN sdorganization SDO
               ON SiteD.siteid = SDO.org_id 
              and SDO.name = 'MAPL' 

         LEFT JOIN sduser U
            ON WO.requesterid = U.userid 

            LEFT JOIN aaauser AU
               ON U.userid = AU.user_id

   where 
          statusname = 'Open' 
      and WO.createdtime >= '1352678400000' 
   order by 
      WO.workorderid