从基础项查询的连接表中选择的有效技术?

时间:2017-05-24 00:10:14

标签: sql postgresql

我有一个非常标准的数据库设置,其中包含父子关系。像父表,子表和parent_child_relationship表这样的东西,其中父有很多并且属于很多孩子(所以不是严格的父子)。

我想要做的是,在为我的API编写SQL时,拉出具有特定ID的父级,然后同时获取该关系中所有子级的子ID。

我目前只在两个查询中执行此操作 - select * from parents where id = ?select child_id as id from parent_child_relationship where parent_id = ?

我很好奇的是:在一个查询中有没有什么特别好的方法可以做到这一点?我在表单

中尝试了像array_agg这样的东西
select parents.*, array_agg(parent_child_relationship.child_id)
from parents join parent_child_relationship
  on parents.id = parent_child_relationship.parent_id
where parents.id = ?
group by parents.id, parents.otherfield, parents.yetanotherfield

但这是非常低效的(当我在父母身上有一堆这样的关系时),因为你实际上最终需要在那里做一个不同的过滤器,并且再次:非常慢。我测试的真实世界查询花了5分钟才完成。

我正在使用EXPLAIN的不同版本来解决自己的问题,但我认为这种需求可能是适度的,并且有一种最好的方法可以做到这一点。

我也可以随时为每个关系继续进行一次查询。这只是一个我可以简化一些东西的地方。

2 个答案:

答案 0 :(得分:1)

关于你想要什么的非常好的博客 - 显示一行带有填充的儿童ID over array_to_string(array_agg())

  

虽然您的原始查询没有array_to_string,但这可能是   差异制造者

http://www.craigkerstiens.com/2013/04/17/array-agg/

实施例

 SELECT 
      users.email,
      array_to_string(array_agg(projects.name), ',')) as projects
    FROM
      projects,
      tasks,
      users
    WHERE projects.id = tasks.project_id
      AND tasks.due_at > tasks.completed_at
      AND tasks.due_at > now()
      AND users.id = projects.user_id
    GROUP BY 
      users.email

答案 1 :(得分:1)

您可以尝试这个版本:

parent_child_relationship(parent_id, child_id)

我不确定为什么你的版本会很慢。 。 。除非您缺少索引。两个版本都需要 if(foo) { //your code here } 上的索引。