我发现自己处于SQL查询的一个不可行的情况,我希望我遗漏了一些东西或者可能会学到一些新知识。我正在使用的DB2数据库的结构并不是完全针对这种查询构建的,但我的任务是...
假设我们有表人和表组。组可以包含多个人,一个人可以是多个组的一部分。是的,它已经很乱了。无论如何,有两个中间表将两者联系起来。问题是我需要从一个组列表开始,获取这些组中的所有人,然后获得所有与之关联的组,这将是初始组集的超集。这意味着从群体开始,加入群众,然后再次返回并加入群组。我也需要结果集中两个表的信息,因此排除了许多技术。
我必须将其与许多其他表格联系以获取更多信息,并且查询变得庞大,繁琐且缓慢。我想知道是否有一些方法可以从People开始,将它加入Groups,然后指定如果一个人有一组在提供的组中(通过子查询完成),那么所有组该人应该退还。我不知道如何实现这一点,但我在想(希望)有一种相对干净的方法可以在SQL中实现这一点。
一个快速而又肮脏的例子:
SELECT ...
FROM GROUPS g
JOIN LINKING_A a
ON g.GROUPID = a.GROUPID
AND GROUPID IN (subquery)
JOIN LINKING_B b
ON a.GROUPLIST = b.GROUPLIST
JOIN PEOPLE p
ON b.PERSONID = p.PERSONID
--This gets me all people affiliated with groups,
-- but now I need all groups affiliated with those people...
JOIN LINKING_B b2
ON p.PERSONID = b2.PERSONID
JOIN LINKING_A a2
ON b2.GROUPLIST = a.GROUPLIST
JOIN GROUPS g2
ON a2.GROUPID = g.GROUPID
然后我可以在结果集中返回p和g2中的信息。你可以看到我遇到麻烦的地方。这是很多加入一些大型表,更不用说在这个查询中执行的一些其他连接。我需要能够通过将PEOPLE加入GROUPS进行查询,然后指定如果任何人具有子查询中的关联组,则应该返回与PEOPLE中该条目相关联的所有组。我认为GROUP BY可能只是那件事,但我还没有用过那个真正知道的东西。因此,如果Bill是A,B和C组的一部分,并且我们的子查询返回包含A组的集合,则结果集应包括Bill以及A,B和C组。
答案 0 :(得分:0)
以下是获取所提供的组列表中的人员所在的所有组的较短方法。这有帮助吗?
Select g.*
From Linking_B b
Join Linking_B b2
On b2.PersonId = b.PersonId
Join Group g
On g.GroupId = b2.GroupId
Where b.Groupid in (SubQuery)
答案 1 :(得分:0)
我不清楚你为什么同时拥有Linking_A和Linking_B。通常,您需要表示两个主表之间的多对多关系是具有GroupID和PersonId的单个关联表。
我经常建议使用“公用表表达式”[CTE],以帮助您将问题分解成更容易理解的块。使用WITH子句指定CTE,在启动主SELECT查询之前可以包含多个CTE。
我将假设您要开始的组列表由您的子查询指定,因此这将是第一个CTE。下一个选择属于这些组的人。然后,查询的最后一部分选择那些人所属的组,并从两个主表中返回列。
WITH g1 as
(subquery)
, p1 as
(SELECT p.*
from g1
join Linking a1 on g1.groupID=a1.groupID
join People p on p.personID=a1.personID )
SELECT p1.*, g2.*
from p1
join Linking a2 on p2.personID=a2.personID
join Groups g2 on g2.groupID=a2.groupID
答案 2 :(得分:0)
我想我会首先建立你想要记录的人的列表,然后用它来查询那些人的所有组。这将适用于任意数量的链接表,并添加了相应的连接:
with persons_wanted as
(
--figure out which people are in a group you want to include
select p.person_key
from person p
join link l1
on p.person_key = l1.person_key
join groups g
on l1.group_key = g.group_key
where g.group name in ('GROUP_I_WANT_PEOPLE_FROM', 'THIS_ONE_TOO')
group by p.person_key --we only want each person_key once
)
--now pull all the groups for the list of people in at least one group we want
select p.name as person_name, g.name as group_name, ...
from person p
join link l1
on p.person_key = l1.person_key
join groups g
on l1.group_key = g.group_key
where p.person_key in (select person_key from persons_wanted);