如何在SQL中查询任意子关系的"父"?

Ian*_*lor 6 sql postgresql

我正在寻找最简单,最有效的SQL查询来team从给定的单元中检索单个查询event.但是event可能与team它没有直接关系,它可能与表关系层次结构中的任何级别相关.


建立

这是我的架构的简单表示:

在此输入图像描述

有几点需要注意:

  • teams可以有很多collections,appswebhooks.
  • collections也可以有很多webhooks.
  • webhooks可以属于team或者collection,但只能属于一个.
  • events 可以属于任何对象,但只能属于一个对象.

这似乎是大多数SaaS类型公司所拥有的相当基本的设置(例如Slack或Stripe).所有内容都归入"团队",用户可以将其作为成员进行交互.


问题

鉴于该设置,我想创建一个解决...的SQL查询...

找到一个事件的团队id.

我可以轻松编写直接或间接通过特定方式查找父团队的查询.例如...

找到直接相关的"团队活动"团队.

SELECT teams.*
FROM teams
JOIN events ON events.team_id = teams.id
WHERE events.id = ${id}
Run Code Online (Sandbox Code Playgroud)

要么...

找到间接相关的"收集活动" 团队.

SELECT teams.*
FROM teams
JOIN collections ON collections.team_id = teams.id
JOIN events ON events.collection_id = collections.id
WHERE events.id = ${id}
Run Code Online (Sandbox Code Playgroud)

Webhooks变得更复杂,因为它们可以通过两种不同的方式相关联......

找到间接相关的"webhook事件" 团队.

SELECT teams.*
FROM teams
JOIN collections ON collections.team_id = teams.id
JOIN webhooks AS team_webhooks ON team_webhooks.team_id = teams.id
JOIN webhooks AS collection_webhooks ON collection_webhooks.collection_id = collections.id
JOIN events AS team_webhook_events ON team_webhook_events.webhook_id = team_webhooks.id
JOIN events AS collection_webhook_events ON collection_webhook_events.webhook_id = collection_webhooks.id
WHERE team_webhook_events.id = ${id}
OR collection_webhook_events.id = ${id}
Run Code Online (Sandbox Code Playgroud)

我不确定我是应该这样写,还是UNION改用...

SELECT teams.*
FROM teams
JOIN webhooks ON webhooks.team_id = teams.id
JOIN events ON events.webhook_id = webhooks.id
WHERE events.id = ${id}

UNION

SELECT teams.*
FROM teams
JOIN collections ON collections.team_id = teams.id
JOIN webhooks ON webhooks.collection_id = collections.id
JOIN events ON events.webhook_id = webhooks.id
WHERE events.id = ${id}
Run Code Online (Sandbox Code Playgroud)

......不确定哪种性能更好.


正如您所看到的,通过所有这些路径,单个事件与给定团队相关的方式有很多种!因此,当我尝试编写"全包围"查询时,它最终变得非常复杂......

潜在的解决方案#1

这样做UNION,我想我可以做出一堆查询,并将它们组合在一起,虽然这似乎可能是浪费?

SELECT teams.*
FROM teams
JOIN events ON events.team_id = teams.id
WHERE events.id = ${id}

UNION

SELECT teams.*
FROM teams
JOIN apps ON apps.team_id = teams.id
JOIN events ON events.app_id = apps.id
WHERE events.id = ${id}

UNION

SELECT teams.*
FROM teams
JOIN collections ON collections.team_id = teams.id
JOIN events ON events.collection_id = collections.id
WHERE events.id = ${id}

UNION

SELECT teams.*
FROM teams
JOIN webhooks ON webhooks.team_id = teams.id
JOIN events ON events.webhook_id = webhooks.id
WHERE events.id = ${id}

UNION

SELECT teams.*
FROM teams
JOIN collections ON collections.team_id = teams.id
JOIN webhooks ON webhooks.collection_id = collections.id
JOIN events ON events.webhook_id = webhooks.id
WHERE events.id = ${id}
Run Code Online (Sandbox Code Playgroud)

潜在的解决方案#2

使用多个JOINs我想我可能能够加入所有不同的事件所有者组合,与他们的关系teams?虽然这似乎也很多JOIN......

SELECT teams.*
FROM teams

JOIN apps ON apps.team_id = teams.id
JOIN collections ON collections.team_id = teams.id
JOIN webhooks AS team_webhooks ON team_webhooks.team_id = teams.id
JOIN webhooks AS collection_webhooks ON collection_webhooks.collection_id = collections.id

JOIN events AS app_events ON app_events.app_id = apps.id
JOIN events AS collection_events ON collection_events.collection_id = collections.id
JOIN events AS team_events ON team_events.team_id = teams.id
JOIN events AS collection_webhook_events ON collection_webhook_events.webhook_id = collection_webhooks.id
JOIN events AS team_webhook_events ON team_webhook_events.webhook_id = team_webhooks.id

WHERE app_events.id = ${id}
OR collection_events.id = ${id}
OR team_events.id = ${id}
OR collection_webhook_events.id = ${id}
OR team_webhook_events.id = ${id}
Run Code Online (Sandbox Code Playgroud)

问题

  • 这些潜在解决方案中的任何一种都是最佳方式吗?
  • 是否有更有效的方式来编写它?
  • 是否有更简单,更易于阅读的方式来编写它?

编辑:我不认为这个问题是重复的!

昨天,我问"如何查询SQL中的嵌套关​​系?" ,它涉及类似的数据结构(因为它是相同的),并以类似的方式编写.但是,据我所知,这个问题实际上与此问题相反.

在第一次,我问如何......

通过ID查找与给定用户相关(直接或间接)的所有事件.或者更一般地说,给定"父"的ID,在树状数据模型中找到所有可能的后代.

但在这一个,我问如何......

按ID查找任意事件的团队.或者更一般地说,给定一个任意"子"的ID,可以将其附加到层次结构的任何级别的树状数据模型中,找到其匹配的父级.(这基本上与第一个问题相反.)

据我所知,它们涉及不同的解决方案.第一个似乎涉及在遍历树时执行一系列查询,收集所有事件.第二个(这个),我不太确定,但似乎需要首先构建所有连接的模型,然后检查它们中的哪一个匹配特定事件.

请帮我把它标记为不重复!

双重编辑:好的,不再标记为重复!感谢:D

baz*_*012 3

通过 ID 查找任意赛事的队伍

从事件表中获取左连接并查看哪个对象返回 team_id 使用它。

select coalesce(e.team_id,a.team_id,c.team_id,w.team_id) eteam_id 
from events e 
   left join apps a on e.app_id=a.id 
   left join collections c on c.id=e.collection_id 
   left join webhooks w on w.id=e.webhook_id 
   left join teams t on t.id=e.team_id 
where e.id=${id};
Run Code Online (Sandbox Code Playgroud)

如果您想要最终团队的所有数据,只是为了完整起见:

select t.* from teams t 
join 
(select coalesce(e.team_id,a.team_id,c.team_id,w.team_id) eteam_id
from events e left join apps a on e.app_id=a.id 
left join collections c on c.id=e.collection_id 
left join webhooks w on w.id=e.webhook_id 
left join teams t on t.id=e.team_id 
where e.id=1) t1 
on t.id=eteam_id;
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

417 次

最近记录:

8 年,6 月 前