2017-10-04 1 views
0

記事はtagのあるのテーブルを照会し、その記事の行に属するすべての(関連性のない)タグに照会します。GROUP BYのすべての列を指定する必要なしにサブクエリからSELECT

例のテーブルやクエリ:

CREATE TABLE article (id SERIAL, body TEXT); 
CREATE TABLE article_tag (article INT, tag INT); 
CREATE TABLE tag (id SERIAL, title TEXT); 

SELECT DISTICT ON (id) 
    q.id, q.body, STRING_AGG(q.tag_title, '|') tags 
FROM (
    SELECT a.*, tag.title tag_title 
    FROM article a 
     LEFT JOIN article_tag x ON a.id = tag.article 
     LEFT JOIN tag ON tag.id = x.tag 
    WHERE tag.title = 'someTag' 
) q 
GROUP BY q.id 

Postgresはq.bodyGROUP BYに含まれなければならないことを要求し、上記の実行:サブクエリqにはないので、私はそれを理解したよう

ERROR: column "q.body" must appear in the GROUP BY clause or be used in an aggregate function 

、それはですPRIMARYキーを含めます。

私はまったくDISTINCT ONがそれを補うと思っていましたが、そうは思われません。

GROUP BY節にすべての列をリストする必要がないように、サブクエリの列をPRIMARYとしてマークする方法はありますか?

の場合にはすべての列をGROUP BY節に記載する必要がありますが、これには相当なコストがかかりますか?

EDIT:詳しく説明するため、GROUP BYを使用する場合PostgreSQL 9.1のであなたは、例えば、供給ノンプライマリ(すなわち機能依存)キーを持っていないクエリを次は正常に動作します:私は(何とかq.idが主キーであることを示すことによって)サブクエリと同じ動作、しかしを活用することができれば、私は思っていた

SELECT a.id, a.body, STRING_AGG(tag.title, '|') tags 
FROM article a 
    LEFT JOIN article_tag x ON a.id = tag.article 
    LEFT JOIN tag ON tag.id = x.tag 
GROUP BY a.id 

+1

可能な重複https://stackoverflow.com/questions/4611897/group-by-aggregate-function-confusion-in-sql) – waka

+1

集計関数を使用するため、すべての非集計列をグループ化する必要があります。 – eurotrash

+0

は、GROUP BYで非主キーを指定する必要がないことを意味するように編集しました(したがって、上記の質問と重複しない理由) – Dwelle

答えて

1

プライマリキーをサブクエリでラップすると悲しいことにうまく動作せず、提案したように「マークする」方法がわかりません。

あなたはwindow functiondistinctを使用してこの回避策を試すことができます。

CREATE TABLE test1 (id serial primary key, name text, value text); 
CREATE TABLE test2 (id serial primary key, test1_id int, value text); 

INSERT INTO test1(name, value) 
      values('name1', 'test01'), ('name2', 'test02'), ('name3', 'test03'); 

INSERT INTO test2(test1_id, value) 
      values(1, 'test1'), (1, 'test2'), (3, 'test3'); 

SELECT DISTINCT ON (id) id, name, string_agg(value2, '|') over (partition by id) 
    FROM (SELECT test1.*, test2.value AS value2 
      FROM test1 
      LEFT JOIN test2 ON test2.test1_id = test1.id) AS sub; 

id name string_agg 
1 name1 test1|test2 
2 name2 null 
3 name3 test3 

Demo

[SQLでGROUP BYは/集計機能の混乱](の
0

問題は外側のSELECTにあります。カラムを集約するか、 のどちらかのグループを使用する必要があります。 Postgresは、q.body - それをグループ化するか、集約を計算するかを指定する必要があります。少し厄介なように見えますが、うまくいくはずです。

SELECT DISTICT ON (id) 
    q.id, q.body, STRING_AGG(q.tag_title, '|') tags 
FROM (
    SELECT a.*, tag.title tag_title 
    FROM article a 
     LEFT JOIN article_tag x ON a.id = tag.article 
     LEFT JOIN tag ON tag.id = x.tag 
    WHERE tag.title = 'someTag' 
) q 
GROUP BY q.id, q.body 
--    ^^^^^^ 

もう一つの方法は、idと集約tagsが、それにbodyに参加取得するクエリを作成することです。あなたが望むなら、私は例を作ることができます。

+0

必要はありません。私の質問は、サブクエリからではなく、 'article'テーブルから直接選択した場合と同じ方法で回避できるかどうかでした。 – Dwelle

関連する問題