我有一个非常标准的数据库设置,其中包含父子关系。像父表,子表和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的不同版本来解决自己的问题,但我认为这种需求可能是适度的,并且有一种最好的方法可以做到这一点。
我也可以随时为每个关系继续进行一次查询。这只是一个我可以简化一些东西的地方。
答案 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
}
上的索引。