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

Posted

技术标签:

【中文标题】MySQL:根据已选择行中的值选择行【英文标题】:MySQL: Select rows based on values in already selected rows 【发布时间】:2014-05-13 02:42:12 【问题描述】:

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

我尝试使用 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:成员目标 (目标成员已经完成或设定为目标)

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

所需结果: 连接两个表并选择状态为 goalcomplete 或父或祖父目标状态为 goalcomplete 的所有行。

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

A2C2 被包括在内,因为他们的父母AC 的状态为goalA2-1C1-1 被包括在内,因为他们的祖父母的状态为@ 987654337@。不包括B 及其子目标和孙目标,因为memberObjectives 表中没有B 的状态为completegoal

我最近的尝试,我知道还没有接近如下:

SELECT DISTINCT mo.objective, mo.member, o.name, mo.status 
  FROM objectives AS o
  LEFT JOIN (SELECT * FROM memberObjectives 
    WHERE member = '001') AS mo ON o.id = mo.objective
  LEFT JOIN objectives AS o2 ON o2.id = o.parent
  LEFT JOIN objectives AS o3 ON o3.id = o2.parent 
  GROUP BY o.id

感谢您提供的任何帮助!

【问题讨论】:

如果您的 ID 是数字而不是 A、A1... 等,这将很容易。您只需要 A 吗?或者这只是你的例子?因为你可以从 A 中过滤掉。问题是祖父母不能只用加入来做 @JohnRuddell As 仅用于示例。我可能想要获得所有具有goalcomplete 状态的As 和Cs,或者具有该状态的父母或祖父母,但不是任何Bs,因为该成员没有完成任何Bs 或将它们设置为目标。 我目前想知道是否有办法加入表格,所以我最终得到了两个额外的列 parentStatusgrandparentStatus,这样如果这些列中的任何一个或原始的 @ 987654353@ 列是 goalcomplete 包含在结果中。 (WHERE status = 'goal' OR status = 'complete' OR parentStatus = 'goal' OR parentStatus = 'complete' OR grandparentStatus = 'goal' OR grandparentStatus = 'complete') 【参考方案1】:

无法测试,但试试这个:

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')

这应该为您提供状态目标或完成的记录以及父母拥有该记录的记录。我由你决定将它扩展到祖父。希望对您有所帮助。

【讨论】:

谢谢!它不喜欢 objectives AS o 在第二次被调用时不是唯一的这一事实。我修正了一些错别字,并给objectives 的第二个电话一个独特的别名。现在它说,#1054 - Unknown column 'mo.objective' in 'on clause'。这是当前查询:SELECT mo.objective, mo.member, o.name, mo.status FROM objectives AS o LEFT JOIN memberObjectives AS mo ON o.id=mo.objetive WHERE status='goal' or status='complete' OR o.id IN(select parent from objectives o2 inner join memberObjectives mo2 on o2.parent=mo.objective WHERE status='goal' or status='complete') 这仅返回具有 GOAL 和 COMPLETE 的两行。它不会添加子孙。【参考方案2】:

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

如果您可以通过作为 A 的 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 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

【讨论】:

感谢您的回答。我们越来越近了,我正在学习一些新东西。查看 FIDDLE,获得所需结果的唯一查询是第一个,但那是因为它正在寻找 As。解决方案需要基于 status 等于 goalcomplete 对于自身、其父级或祖父级。我用C 目标更新了问题,以更好地显示所需的结果。再次感谢您迄今为止的帮助!【参考方案3】:

我创建了一个目前似乎可行的解决方案。它添加了更多连接,以在每一行中包含 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

根据我最初的问题,解决方案不是根据已选择行中的值选择行,而是连接表以具有额外的列来检查来自其他行的必要值。

【讨论】:

此解决方案有效,但我愿意接受更优雅的解决方案作为答案。

以上是关于MySQL:根据已选择行中的值选择行的主要内容,如果未能解决你的问题,请参考以下文章

根据 CSV 文件行中的值确定数据类型

MySQL,根据列值从不同的行中选择

MySQL,根据 JSON 数组中的值选择记录

根据熊猫中多列中的值从数据框中选择行

根据熊猫中多列中的值从数据框中选择行

根据熊猫中多列中的值从数据框中选择行