sql - 获取二维数据的有效方法

标签 sql postgresql

为了举例,假设我有以下模型:

  • 团队
  • 每支球队都有任意数量的球迷

在 SQL 中,这意味着您最终会得到以下表格:

  • 团队:标识符、名称
  • 粉丝:标识符,名字
  • team_fan:team_identifier,fan_identifier

我正在寻找一种检索方法:

  • 所有团队,以及
  • 对于每支球队,他/她的名字以“A”开头的前 5 名球迷。

执行此操作的有效方法是什么?

  1. 在我目前的幼稚方法中,我做 <# 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
      
  2. 应该有更好的方法来做到这一点。

我可以像现在一样先检索所有团队,然后执行以下操作:

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/

相关文章:

sql - 跨多个表添加序列值

postgresql - 如何在 Postgresql 上使用 Solr 和索引表

MySQL Over 从 SQL 到 MySQL 的转换

MySQL 去年同一天

python - 使用在服务器上运行的 python 脚本和存储过程有什么区别?

postgresql - 将字符串插入文本 [] 列

ruby-on-rails - 如何在创建时使用主键的值设置另一列

sql - 如何通过每个产品单行的产品获得不同的价格

sql - 从 postgres 中的十进制值中删除 (.)

sql - 使用 SSIS 包加载数据时理解间歇性不一致的问题