MySQL:根据已选择的行中的值选择行

时间:2014-04-02 03:17:41

标签: mysql sql select join union

我想根据已经选择的行中的值从数据库中的连接表中选择行。基本上,如果父级或granparent行处于活动状态,则还会在结果中包含子级或孙级行。

我尝试使用JOINSUNIONS的不同组合来获得我想要的结果但没有成功。

以下是我的示例数据:

表1:目标 (成员可以设定目标或完成的目标)

id   | name     | parent
---------------------------
A    | Obj A    | null 
A1   | Obj A1   | A 
A2   | Obj A2   | A
A2-1 | Obj A2.1 | A2
B    | Obj B    | null
B1   | Obj B1   | B
B1-1 | Obj B1.1 | B1
C    | Obj C    | null
C1   | Obj C1   | C
C1-1 | Obj C1.1 | C1

表2:memberObjectives (目标成员已完成或设定为目标)

id | objective | member | status
-----------------------------------
1  | A         | 001    | goal
2  | A1        | 001    | complete
3  | C         | 001    | goal

期望的结果:加入两个表并选择状态为goalcomplete的所有行或父级或祖父级目标的状态为{{1}的所有行}或goal

complete

objective | member | name | status ------------------------------------------ A | 001 | Obj A | goal A1 | 001 | Obj A1 | complete A2 | 001 | Obj A2 | null A2-1 | 001 | Obj A2-1 | null C | 001 | Obj C | goal C1 | 001 | Obj C1 | null C1-1 | 001 | Obj C1.1 | null A2包括在内,因为他们的父母C2A的状态为Cgoal以及{{1}包括在内,因为他们的祖父母的状态为A2-1C1-1及其子级和格式目标未包括在内,因为goal表格中没有B个状态为BmemberObjectives

我最近的尝试,我知道甚至不接近如下:

complete

感谢您提供任何帮助!

3 个答案:

答案 0 :(得分:0)

无法测试它,但试试这个:

SELECT mo.objective, mo.member, o.name, mo.status 
  FROM objectives AS o
  LEFT JOIN memberObjectives o.id=mo.objetive
WHERE status='goal' or status='complete'
OR o.id IN(select parent from objetives o inner join memberObjectives mo on o.parent=mo.objetive WHERE status='goal' or status='complete')

这应该为您提供状态目标或完成的记录以及父母拥有该记录的记录。我是由你来扩展到格兰父亲。希望它有所帮助。

答案 1 :(得分:0)

您可以查看三个查询:请参阅FIDDLE了解工作示例

如果你可以通过id作为A进行过滤,那么这个查询将完全符合您的要求。

SELECT t.id as objective, mo.member, t.name, mo.status from(
  SELECT * FROM objective o
)AS t
LEFT JOIN memberObjective mo ON mo.objective = t.id
WHERE t.id in(SELECT objective FROM memberObjective)
OR t.parent in(SELECT o.id FROM objective o where o.id like "%A%")

此查询获取父级,但不是祖父级。

SELECT t.id as objective, mo.member, t.name, mo.status from(
  SELECT * FROM objective o
)AS t
LEFT JOIN memberObjective mo ON mo.objective = t.id
WHERE t.id in(SELECT objective FROM memberObjective)
OR t.parent in(SELECT o.id FROM objective o join memberObjective mo on mo.objective = o.id)

此查询获取父级和祖父级,但它不会过滤掉B ..数据库中没有足够的数据来添加祖父母,因为A2在您的表中只出现两次,而它的父和id

SELECT t.id as objective, mo.member, t.name, mo.status from(
  SELECT * FROM objective o
)AS t
LEFT JOIN memberObjective mo ON mo.objective = t.id
WHERE t.id in(SELECT objective FROM memberObjective)
OR t.parent in(SELECT o.id FROM objective o left join memberObjective mo on mo.objective = o.id) 
----  you could add LIMIT 4 to get the correct results but thats another semi hacky way to do it

答案 2 :(得分:0)

我创建了一个似乎现在正在运行的解决方案。它添加了一些连接,以便在每行中包含parentStatusgrandparentStatus列。现在,如果statusparentStatusgrandparentStatusgoalcomplete,则该行将包含在结果中。

以下MySQL查询的结果如下:

objective | member | name     | status    | parentStatus | grandparentStatus
------------------------------------------------------------------------------
A         | 001    | Obj A    | goal      | null         | null
A1        | 001    | Obj A1   | complete  | goal         | null
A2        | 001    | Obj A2   | null      | goal         | null
A2-1      | 001    | Obj A2-1 | null      | null         | goal
C         | 001    | Obj C    | goal      | null         | null
C1        | 001    | Obj C1   | null      | goal         | null
C1-1      | 001    | Obj C1.1 | null      | null         | goal

以下是MySQL查询:

SELECT DISTINCT * FROM objectives AS o  
  LEFT JOIN (SELECT * FROM memberObjectives WHERE member = '001') 
    AS mo ON mo.objective = o.id 
  LEFT JOIN (SELECT mo2.status AS parentStatus, mo2.objective AS parentObjective
    FROM memberObjectives AS mo2
    LEFT JOIN objectives AS o2 ON o2.parent = mo2.objective 
    WHERE mo2.member = '001') 
      AS parent ON parent.parentObjective = o.parent
  LEFT JOIN (SELECT mo3.status AS grandparentStatus, mo3.objective AS grandparentObjective 
    FROM memberObjectives AS mo3
    LEFT JOIN objectives AS o3 ON o3.parent = mo3.objective 
    WHERE mo3.member = '001') 
      AS grandparent ON grandparent.grandparentObjective = o.parent
  WHERE mo.status = 'goal' OR mo.status = 'complete' 
    OR parentStatus = 'goal' OR parentStatus = 'complete' 
    OR grandparentStatus = 'goal' OR grandparentStatus = 'complete' 
  GROUP BY o.id

根据我的原始问题,解决方案不是基于已选择的行中的值选择行,而是连接表以使用额外的列来检查来自其他行的必要值。