2017-10-04 12 views
0

想法是查詢article表,其中文章有給定的tag,然後到STRING_AGG屬於該文章行的所有(甚至不相關的)標籤。從子查詢中進行選擇,而不必指定GROUP BY中的所有列

示例表和查詢:

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.body必須包含在GROUP BY

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

據我瞭解,這是因爲子查詢q不包括任何主鍵。

我天真地認爲DISTINCT ON會補充,但它似乎並不如此。

是否有辦法將子查詢中的列標記爲PRIMARY,以便我們不必列出GROUP BY子句中的所有列?

如果我們必須列出GROUP BY子句中的所有列,這是否會產生顯着的性能費用?

編輯:闡述,因爲你PostgreSQL 9.1不必供給非主(即功能上依賴)鍵使用GROUP BY時,例如下面的查詢工作正常:

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 

我在想,如果我可以利用相同的行爲,但子查詢(通過某種方式,表明q.id是主鍵)。

+1

[SQL中GROUP BY /聚合功能混亂(的可能的複製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

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