MySQL:根据已选择行中的值选择行
Posted
技术标签:
【中文标题】MySQL:根据已选择行中的值选择行【英文标题】:MySQL: Select rows based on values in already selected rows 【发布时间】:2014-05-13 02:42:12 【问题描述】:我想根据已选择的行中的值从数据库中的连接表中选择行。基本上,如果父行或祖父行处于活动状态,则还要在结果中包含子行或孙行。
我尝试使用 JOINS
和 UNIONS
的不同组合来获得我想要的结果,但没有成功。
这是我的示例数据:
表 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
所需结果: 连接两个表并选择状态为 goal
或 complete
或父或祖父目标状态为 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
和C2
被包括在内,因为他们的父母A
和C
的状态为goal
和A2-1
和C1-1
被包括在内,因为他们的祖父母的状态为@ 987654337@。不包括B
及其子目标和孙目标,因为memberObjectives
表中没有B
的状态为complete
或goal
。
我最近的尝试,我知道还没有接近如下:
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 中过滤掉。问题是祖父母不能只用加入来做 @JohnRuddellA
s 仅用于示例。我可能想要获得所有具有goal
或complete
状态的A
s 和C
s,或者具有该状态的父母或祖父母,但不是任何B
s,因为该成员没有完成任何B
s 或将它们设置为目标。
我目前想知道是否有办法加入表格,所以我最终得到了两个额外的列 parentStatus
和 grandparentStatus
,这样如果这些列中的任何一个或原始的 @ 987654353@ 列是 goal
或 complete
包含在结果中。 (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,获得所需结果的唯一查询是第一个,但那是因为它正在寻找A
s。解决方案需要基于 status
等于 goal
或 complete
对于自身、其父级或祖父级。我用C
目标更新了问题,以更好地显示所需的结果。再次感谢您迄今为止的帮助!【参考方案3】:
我创建了一个目前似乎可行的解决方案。它添加了更多连接,以在每一行中包含 parentStatus
和 grandparentStatus
列。现在,如果 status
、parentStatus
或 grandparentStatus
为 goal
或 complete
,则该行将包含在结果中。
下面的 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:根据已选择行中的值选择行的主要内容,如果未能解决你的问题,请参考以下文章