MySQL:加入内部WHERE子句

时间:2011-10-06 10:30:28

标签: mysql join

[编辑]

我现在发现了这种方法的缺陷。当为每个位置定义一名机组成员时,它运作良好,但完全跳过没有填充一些机组人员位置的行。

这是不可取的,只是从每个船员必须有船员和司机的角度来看,但此后的其他所有位置都可能是空的。

有关如何做到这一点的任何想法?阅读起来,看起来我可能需要模拟某种完全外连接。

[原稿]

我的数据库有一个供用户使用的表(称为ign_users):

-----------------------------------
¦ user_id ¦ RealName  ¦ surname   ¦
-----------------------------------
¦ 1       ¦ Alpha     ¦ Smith     ¦
-----------------------------------
¦ 2       ¦ Bravo     ¦ Jones     ¦
-----------------------------------
¦ 3       ¦ Charlie   ¦ Brown     ¦
-----------------------------------
¦ 4       ¦ Delta     ¦ White     ¦
-----------------------------------

我创建了一个新表来创建工作人员(称为as_crew):

------------------------------------------------
¦ name  ¦ crew_leader ¦ driver ¦ crew3 ¦ crew4 ¦
------------------------------------------------
¦ A     ¦ 1           ¦ 2      ¦ 3     ¦ 4     ¦
------------------------------------------------
¦ B     ¦ 2           ¦ 4      ¦ 1     ¦ 2     ¦
------------------------------------------------

我希望能够做的就是加入这两个人,以便我得到每个人的全名(即真实姓名和姓氏)。

我可以一次做一个人。例如,以下内容将返回船员领队的全名:

SELECT c.name, CONCAT(u.RealName, ' ', surname)
FROM as_crew c, ign_users u
WHERE c.crew_leader=u.user_id

但是,当我尝试将其与另一个查询结合在一起时出现错误,例如:

SELECT c.name, CONCAT(u.RealName, ' ', surname)
FROM as_crew c, ign_users u
WHERE c.crew_leader=u.user_id
JOIN
  (SELECT c.name, CONCAT(u.RealName, ' ', surname)
   FROM as_crew c, ign_users u
   WHERE c.DRIVER=u.user_id) AS t
ON c.name=t.name

我认为这是由WHERE子句引起的,但如果我只是从SELECT语句中删除它们并将它们放在外面,我就无法弄清楚如何得到这个结果。

对于船员3和船员4(以及其他人 - 他们去船员8),我只想将船员连接成一个结果。

感谢。

3 个答案:

答案 0 :(得分:1)

首先,我会尝试将数据标准化为每个工作人员一行。从那里开始,你加入......我在最终输出中添加了额外的列,以查看记录的来源/最终消失的位置。

如果您只想要一个特定的Crew,只需在每个“SELECT / FROM”中添加相同的“WHERE”子句,因为它分解为单独的行......正如我在{}下面评论过的那样

select
      PreQuery.Name,
      PreQuery.CrewPosition,
      PreQuery.PersonID,
      CONCAT(u.RealName, ' ', U.surname) as  PersonsName
   from
      ( select  c.Name, 
                "Crew Leader " as CrewPosition,
                c.Crew_Leader as PersonID
           from as_crew c
           { SPECIFIC WHERE CLAUSE }
        union 
        select  c.Name, 
                "Driver      " as CrewPosition,
                c.Driver as PersonID
           from as_crew c
           { SPECIFIC WHERE CLAUSE }
        union 
        select  c.Name, 
                "Crew3       " as CrewPosition,
                c.Crew3 as PersonID
           from as_crew c
           { SPECIFIC WHERE CLAUSE }
        union 
        select  c.Name, 
                "Crew4       " as CrewPosition,
                c.Crew4 as PersonID
           from as_crew c 
           { SPECIFIC WHERE CLAUSE }  ) PreQuery

      JOIN ign_users u
         on PreQuery.PersonID = u.User_ID

这是一个让所有人都在一行的解决方案...... 根据评论反馈进行修订。

select
      c.Name,
      CONCAT(CL.RealName, ' ', CL.surname) as  CrewLeader,
      CONCAT(dr.RealName, ' ', dr.surname) as  Driver,
      CONCAT( CONCAT(c3.RealName, ' ', c3.surname), ', '
              CONCAT(c4.RealName, ' ', c4.surname) as OtherCrew
   from
      as_crew c
         join ign_users CL
            on c.Crew_Leader = CL.User_ID
         join ign_users dr
            on c.Driver = dr.User_ID
         join ign_users c3
            on c.Crew3 = c4.User_ID
         join ign_users c4
            on c.Crew4 = c4.User_ID

最后......如果给定的工作人员没有所有成员......例如只有船员和司机,但没有船员3或船员4,只需将其改为LEFT JOIN而不是常规的JOIN。

答案 1 :(得分:0)

尝试:

SELECT c1.name, CONCAT(u.RealName, ' ', surname)
FROM as_crew c1, ign_users u
JOIN
  ( (SELECT c.name, CONCAT(u.RealName, ' ', surname)
   FROM as_crew c, ign_users u
   WHERE c.DRIVER=u.user_id) AS t
ON c1.name=t.name )
WHERE c1.crew_leader=u.user_id

你还得到错误吗?

答案 2 :(得分:0)

我认为你试图在union的上下文中使用join关键字。 IE你想互相“加入”结果。

SELECT c.name, CONCAT( u.RealName, ' ', surname )
FROM as_crew c, ign_users u
WHERE c.crew_leader = u.user_id
UNION ALL
SELECT c.name, CONCAT( u.RealName, ' ', surname )
FROM as_crew c, ign_users u
WHERE c.DRIVER = u.user_id
UNION ALL
SELECT c.name, CONCAT( u.RealName, ' ', surname )
FROM as_crew c, ign_users u
WHERE c.crew3 = u.user_id

等等。

编辑:我会为驾驶员号码制作另一张表格,指向机组人员编号,因此您可以只有几个where语句,例如,如果您的机组人员规模发生变化,则无需更新所有表格结构。

Edit2: 试试这个。

SELECT c.name, GROUP_CONCAT(CONCAT( ' ',u.RealName, ' ', u.surname )) 
FROM as_crew c, ign_users u
WHERE c.driver = u.user_id OR c.crew_leader = u.user_id  
OR c.crew3 = u.user_id 
OR c.crew4 = u.user_id 
OR c.crew5 = u.user_id 
OR c.crew6 = u.user_id 
OR c.crew7 = u.user_id 
OR c.crew8 = u.user_id
GROUP BY c.name