我有以下表格:
team: identifier, name
fan: identifier, name
team_fan: team_identifier, fan_identifier
换句话说,团队与粉丝之间存在多对多关系。
我想获取满足某个条件的所有球队;对于每个选定的团队,我想要获取所有粉丝。因此,在我的应用程序中,我希望拥有以下数据结构:
Team A
Fan F1
Fan F2
Team B
Fan F1
Fan F3
Team C
Fan F2
Fan F3
Fan F4
我已经提出了以下解决方案:
[0]默认,典型方法
默认的典型方法是内连接:
select team.name, fan.name
from team
inner join team_fan
on team.identifier = team_fan.team_identifier
inner join fan
on team_fan.fan_identifier = fan.identifier
where ... (team conditions)
这提供了构建数据结构所需的所有信息,如上所示。
很多球队和球迷可以属于多个球队。上面的查询可能不是一个好主意,因为团队和粉丝在结果中是重复的。所有这些重复都需要通过网络传输。
在下面的替代方案中,我正在应用程序中进行JOIN。下面的替代方案可能会更慢,但我还不知道。我想比较并从中学习。
[1]非常天真的方法
首先,我们选择所有团队:
select name from team where ...
然后,对于标识符为X的每个团队,我们选择其粉丝:
select name
from fan
where exists(select 1 from team_fan where team_identifier = X)
这是一个糟糕的解决方案,因为所需查询的数量为1 + number of teams
。此外,多次获取属于多个团队的粉丝。我们可以做得更好。
[2]自上而下的方法
首先,我们选择所有球队。在执行此操作时,我们还会收集属于该团队的所有粉丝:
select name, array(select identifier
from fan
where exists(select 1 from team_fan where fan.identifier = team_fan.fan_identifier and team.identifier = team_fan.team_identifier)) as fans
from team
where ...
然后,在我们的应用程序中,我们构造所有扇形标识符的并集。鉴于这组粉丝标识符,我们可以选择所有粉丝:
select name from fan where identifier in(...)
现在,我有足够的信息在我的应用程序中复制JOIN并构建数据结构,如上所示。
这似乎是一个更好的解决方案。查询数量始终为2.此外,每个团队和每个粉丝仅获取一次。
[3]自下而上的方法
我调用了之前的解决方案top-down
,因为我们正在向父(团队)添加一组子(粉丝)。在这种方法中,我们做反过来:我们正在向孩子(粉丝)添加一组父母(团队)。
首先,让我们选择所有球队:
select name from team where ...
接下来,在我们的应用程序中,我们构建了所有团队标识符的联合。鉴于这组球队标识符,我们可以选择所有球迷:
select name, array(select team_fan.team_identifier from team_fan where fan_identifier = fan.identifier and team_identifier in(...))
from fan
where exists(select 1 from team_fan where fan_identifier = fan.identifier and team_identifier in(...));
现在,我有足够的信息在我的应用程序中复制JOIN并构建数据结构,如上所示。
这似乎也是一个有效的解决方案。同样在这种情况下,查询的数量始终为2.此外,每个团队和每个扇子仅获取一次。
我的问题
所以,回到我的问题:我想要获取满足某个条件的所有团队;对于每个选定的团队,我想要抓住所有粉丝。
目前,我不确定方法2是否优于方法3(反之亦然),或者甚至,如果有更好的方法。任何见解都是受欢迎的。
答案 0 :(得分:0)
进行简单的加入
Select
t.identitfier team_identifier
,t.name team_name
,f.identitfier fan_identifier
,f.name fan_name
From team t
inner join team_fan tf
on t.identifier=tf.team_identifier
/* and --(team condition can be put here) */
inner join fan f on tf.fan_identifier=f.identifier
/*where ... --(or team condition can be put here)*/
答案 1 :(得分:0)
我建议修改选项2并完全删除风扇表。
假设团队数量少于粉丝,这种方法将为您的应用程序返回更少的行,并且可能更高效,因为数组函数不需要在替代行数上执行。
SELECT
name,
array(
SELECT DISTINCT
fan_identifier
FROM team_fan
WHERE team.identifier = team_fan.team_identifier
) as fans
FROM team
WHERE ...