我希望编写最简单、最有效的SQL查询语句,以检索与给定用户相关的所有事件。
设置
这是我模式的简单表示:
需要注意的几点:
users
通过memberships
属于teams
。teams
可以拥有多个collections
、apps
和webhooks
。collections
也可以拥有多个webhooks
。webhooks
只能属于一个team
或collection
。events
可以属于任何对象,但只能属于一个对象。
这看起来像大多数 SaaS 类型公司都会有的基本设置 (例如 Slack 或 Stripe)。所有内容都由团队 "拥有",但用户属于团队并与界面进行交互。
问题
在这种设置下,我想创建一个SQL查询来解决...
查找所有与给定用户通过
id
(直接或间接)相关的事件。
我可以轻松编写查询,以通过特定手段直接或间接地找到它们。例如...
查找所有与用户通过
id
直接 相关的事件。
SELECT *
FROM events
WHERE user_id = ${id}
或者...
通过用户的团队查找所有与用户间接相关的事件。
SELECT events.*
FROM events
JOIN memberships ON memberships.team_id = events.team_id
WHERE memberships.user_id = ${id}
甚至可以...
通过用户所在团队的所有集合间接地找到与其相关的所有事件。
SELECT events.*
FROM events
JOIN collections ON collections.id = events.collection_id
JOIN memberships ON memberships.team_id = collections.team_id
WHERE memberships.user_id = ${id}
Webhooks变得更加复杂,因为它们可以通过两种不同的方式相关联...
查找所有通过用户的团队或集合的任何webhook 间接 相关的事件。
SELECT *
FROM events
WHERE webhook_id IN (
SELECT webhooks.id
FROM webhooks
JOIN memberships ON memberships.team_id = webhooks.team_id
WHERE memberships.user_id = ${id}
)
OR webhook_id IN (
SELECT webhooks.id
FROM webhooks
JOIN collections ON collections.id = webhooks.collection_id
JOIN memberships ON memberships.team_id = collections.team_id
WHERE memberships.user_id = ${id}
)
但是,如您所见,用户与发生的事件之间有很多不同的关联方式,通过所有这些路径!因此,当我尝试查询成功获取所有相关事件时,它最终看起来像...
SELECT *
FROM events
WHERE user_id = ${id}
OR app_id IN (
SELECT apps.id
FROM apps
JOIN memberships ON memberships.team_id = apps.team_id
WHERE memberships.user_id = ${id}
)
OR collection_id IN (
SELECT collections.id
FROM collections
JOIN memberships ON memberships.team_id = collections.team_id
WHERE memberships.user_id = ${id}
)
OR memberships_id IN (
SELECT id
FROM memberships
WHERE user_id = ${id}
)
OR team_id IN (
SELECT team_id
FROM memberships
WHERE user_id = ${id}
)
OR webhook_id IN (
SELECT webhooks.id
FROM webhooks
JOIN memberships ON memberships.team_id = webhooks.team_id
WHERE memberships.user_id = ${id}
)
OR webhook_id IN (
SELECT webhooks.id
FROM webhooks
JOIN collections ON collections.id = webhooks.collection_id
JOIN memberships ON memberships.team_id = collections.team_id
WHERE memberships.user_id = ${id}
)
问题
- 最终的“全部包括”的查询是否非常低效?
- 有更有效的编写方式吗?
- 有没有更简单、更易于阅读的编写方式?