2016-03-21 4 views
0

私が持っているようなクエリ:のようなものになりますpostgresqlでそのようなクエリを効果的に書く方法:連続した行を配列に集約する(列のペアで識別)?

(
    SELECT 
     t1.person_id, 
     t1.created_at, 
     't1' AS type, 
     t1.extra_data AS extra_data 
    FROM table1 AS t1 
) 
UNION 
(
    SELECT 
     t2.person_id, 
     t2.created_at, 
     't2' AS type, 
     t2.extra_data AS extra_data 
    FROM table2 AS t2 
) 
UNION 
(
    SELECT 
     t3.person_id, 
     t3.created_at, 
     't3' AS type, 
     t3.extra_data AS extra_data 
    FROM table3 AS t3 
) 
ORDER BY created_at DESC; 

created_atがタイムスタンプである、と私は具体的な値を省略し、順序を表すために、単純な整数を使用)

person_id | type | created_at | extra_data 
--------- | ---- | ---------- | ---------- 
1   | t1 | 9   | a 
1   | t1 | 8   | b 
2   | t2 | 7   | c 
2   | t2 | 6   | c 
2   | t2 | 5   | d 
1   | t3 | 4   | e 
3   | t3 | 3   | f 

私は最終的なcreated_atとして最大created_atの連続した(person_id、type)の組をグループ化し、配列にextra_dataを集約したい、つまり、次の結果を得たいとします。

person_id | type | created_at | extra_data_array 
--------- | ---- | ---------- | ---------- 
1   | t1 | 9   | [a, b] 
2   | t2 | 7   | [c, c, d] 
1   | t3 | 5   | e 
3   | t3 | 4   | f 

私は窓関数を試しましたが、これを達成する方法を理解することができませんでした。

私の質問は:

1)私の目標を達成するために、単一のクエリを記述するためにどのように?

2)このようなクエリは、index?

2番目の質問に対する私の懸念は、ベース結果がUNIONクエリから選択されるため、インデックスを利用する機会があるかどうかは疑問です。

誰でも、あらゆる種類の助けを借りて、誰でも!

答えて

0

2つの集計関数は、MAXarray_aggです。

私はあなたGROUP場合UNION前にインデックスを適用し、より良い運を持っていると思うので、私はこれを行うだろう:限りは、結果

(
    SELECT 
     t1.person_id, 
     MAX(t1.created_at) AS created_at, 
     't1' AS type, 
     array_agg(t1.extra_data) AS extra_data 
    FROM table1 AS t1 
    GROUP BY t1.person_id 
) 
UNION 
(
    SELECT 
     t2.person_id, 
     MAX(t2.created_at) AS created_at, 
     't2' AS type, 
     array_agg(t2.extra_data) AS extra_data 
    FROM table2 AS t2 
    GROUP BY t2.person_id 
) 
UNION 
(
    SELECT 
     t3.person_id, 
     MAX(t3.created_at) AS created_at, 
     't3' AS type, 
     array_agg(t3.extra_data) AS extra_data 
    FROM table3 AS t3 
    GROUP BY t3.person_id 
) 
ORDER BY created_at DESC; 

しかし、あなたは可能性もUNION最初にしGROUPをあなたGROUP BY person_id, type

カップルより多くのノート:

  • あなたはすべての行からcreated_atextra_dataを取得する必要がありますので、これはまだ、すべてのテーブルにフルテーブルスキャンを行うとしています。これはインタビューの質問のようなものです。「バイナリツリーのノードを印刷するにはどのくらい時間がかかるのですか?」

  • 配列を注文する場合は、array_agg(t1.extra_data ORDER BY t1.created_at)などで配列を並べ替えることができます。これはインデックスがあなたを助けるかもしれないところです。

関連する問題