2017-05-24 14 views
0

親子関係のあるかなり標準的なデータベース設定があります。親テーブル、子テーブル、parent_child_relationshipテーブルのようなもの。親は多くの子を持ち、多くの子に属します(厳密には親子ではありません)。基本項目クエリを使用して結合テーブルから選択する効率的な手法ですか?

私がしたいのは、APIをSQLで記述するときに、特定のIDを持つ親をプルアップし、関係内のすべての子の子IDも取得することです。

私は現在、select * from parents where id = ?select child_id as id from parent_child_relationship where parent_id = ?という2つのクエリでこれを実行しています。

私が気にかけているのは、これを1つのクエリですべて実行する特別な方法はありますか?私は、フォーム

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 

にARRAY_AGGようなものを試したが、(私は親にこれらの関係の束を持っている場合)あなたが実際にそこに明確なフィルタを行うために必要が終わると、これは、かなり非効率的で、そして再び:かなり遅い。私がテストした現実の世界の質問には、5分ほどかかりました。

私はEXPLAINを使って自分自身を理解しようとしていますが、この種の必要性はやや普通だと思っており、これを行うにはベスト・ウェイがありました。

私は常に、各関係ごとに1つのクエリを実行し続けることができます。これはちょうど私がいくつかのものを単純化できる場所のように感じた。

+0

期待される結果は、詰め込まれた子IDを持つ行だけですか? – maSTAShuFu

答えて

1

あなたはこのバージョンを試してみてください:あなたのバージョンが遅くなる理由

select p.*, 
     (select array_agg(pc.child_id) 
     from parent_child_relationship pcr 
     where p.id = pcr.parent_id 
     ) as children 
from parents p 
where p.id = ?; 

私はよく分かりません。 。 。インデックスがない場合を除きます。どちらのバージョンでも、インデックスはparent_child_relationship(parent_id, child_id)になります。

1

あなたが欲しいものについては非常に良いブログ - array_to_string上 詰め子IDを持つ1行を表示する(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 
関連する問題