为了举例,假设我有以下模型:
- 团队
- 每支球队都有任意数量的球迷
在 SQL 中,这意味着您最终会得到以下表格:
- 团队:标识符、名称
- 粉丝:标识符,名字
- team_fan:team_identifier,fan_identifier
我正在寻找一种检索方法:
- 所有团队,以及
- 对于每支球队,他/她的名字以“A”开头的前 5 名球迷。
执行此操作的有效方法是什么?
在我目前的幼稚方法中,我做
<# teams> + 1
查询,比较麻烦:- 第一个:
SELECT * FROM team
然后,对于标识符为
X
的每个团队:SELECT * FROM fan INNER JOIN team_fan ON fan.identifier = team_fan.fan_identifier AND team_fan.team_identifier = X WHERE fan.name LIKE 'A%' ORDER BY fan.name LIMIT 5
- 第一个:
应该有更好的方法来做到这一点。
我可以像现在一样先检索所有团队,然后执行以下操作:
SELECT *
FROM fan
WHERE fan.name LIKE 'A%'
AND fan.identifier IN (
SELECT fan_identifier
FROM team_fan
WHERE team_identifier IN (<all team identifiers from first query>))
ORDER BY fan.name
但是,这种方法忽略了我需要每支球队的前 5 名粉丝的名字以“A”开头的要求。只需添加 LIMIT 5
上面的查询是不正确的。
此外,使用这种方法,如果我有大量团队,我会在第二个查询中将相应的团队标识符发送回数据库(对于 IN (<all team identifiers from first query>)
),这可能会降低性能?
我正在针对 PostgreSQL、Java、Spring 和纯 JDBC 进行开发。
最佳答案
你需要一个三表连接
SELECT team.*, fan.*
FROM team
JOIN team_fan
ON team.team_identifier = team_fan.team_identifier
JOIN fan
ON fan.fan_identifier = team_fan.fan_identifier
现在要进行过滤,您需要执行此操作。
with cte as (
SELECT team.*, fan.*,
row_number() over (partition by team.team_identifier
order by fan.name) as rn
FROM team
JOIN team_fan
ON team.team_identifier = team_fan.team_identifier
JOIN fan
ON fan.fan_identifier = team_fan.fan_identifier
WHERE fan.name LIKE 'A%'
)
SELECT *
FROM cte
WHERE rn <= 5
关于sql - 获取二维数据的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44208900/