2017-09-14 23 views
1

グループ内の少なくとも1つの行がbar='baz'と一致する場合、すべての行をfooでグループ化したいとします。Postgres:GROUP BYの後に一致するパターン

私はそうのようなクエリがある:

SELECT foo, string_agg(bar) 
FROM table 
WHERE bar='baz' 
GROUP BY foo; 

はしかし、これは明らかにbar!=baz行を残します。 グループ内の少なくとも1つが一致する場合、それらの行を含める必要があります。 これを達成する最も良い方法は何ですか?

私は例えば、ARRAY_AGG(バー)といずれかを使用してサブ選択を使用して検討している:

SELECT foo, bars FROM (
    SELECT foo, array_agg(bar) as bars 
    FROM table 
    WHERE 'baz' ANY(bars) 
    GROUP BY FOO 
) 

しかし、これは醜いソリューションのように思えるし、また、私はstring_aggを使用することはできません。

+0

あなたはデータサンプルと期待される結果を追加してくださいだろう?.. –

答えて

1

使用EXISTS

SELECT foo, string_agg(bar) 
FROM table 
WHERE EXIST (SELECT 1 FROM table t WHERE t.bar='baz' AND t.foo = foo) 
GROUP BY foo; 

またはIN Radimのexists答え@に対しても

SELECT foo, string_agg(bar) 
FROM table 
WHERE foo IN (SELECT t.foo FROM table t WHERE t.bar='baz') 
GROUP BY foo; 
+0

ありがとう!サブセレクトを使用する方法はないと思いますか?バーは実際に別のテーブルにあるので、私の実際のクエリはより複雑です。 Postgresが私が知らない何らかのキャッシュをしていない限り、このソリューションがデータベースを2回検索して2倍遅くなるように見えます。 – Agargara

+1

@Agargara私は、例えば 'IN'の解決策がクエリを大幅に遅くする理由は見当たりません。スピードアップが必要な場合は、クエリのインデックスを作成します(ペアとして '(bar、foo)'をキーとして使用します)。 –

+0

ありがとう、あなたは正しいです。遅いのは関連性のない問題(正規表現が多すぎるため)でした。 – Agargara

1

テストbool_orとして有用であることができます:

select foo, string_agg(bar) 
from t 
group by foo 
having bool_or(bar = 'baz') 
+0

これははるかにエレガントで、私はそれを使いたいと思います...しかし、驚くほどテストではそれは既存のソリューション!少なくとも私の特定のアプリケーションでは、bool_orが〜1200msかかるうちに、EXISTSクエリは~800msかかる。 – Agargara

+1

@Agargara私の推測では、 '(foo、bar)'のインデックスは両方が同じように動作するようにしています。 –

関連する問題