Sql 从子查询中选择,而不必指定分组依据中的所有列
其思想是查询一个Sql 从子查询中选择,而不必指定分组依据中的所有列,sql,postgresql,group-by,Sql,Postgresql,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
文章
表,其中一篇文章有一个给定的标记
,然后查询属于该文章行的所有(甚至是不相关的)标记
示例表和查询:
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
不包含任何主键
我天真地认为上的可以补充这一点,但事实似乎并非如此
有没有一种方法可以将子查询中的一列标记为主列,这样我们就不必列出GROUPBY
子句中的所有列
如果我们必须列出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
是主键)。问题在于外部选择
-您也应该聚合列
按他们分组。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
加入其中。如果你愿意,我可以举个例子。很遗憾,当你将主键包装在子查询中时,它不起作用,而且我不知道有什么方法可以像你建议的那样“标记它”
您可以使用窗口功能
和独特功能
尝试此解决方法:
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
由于使用了聚合函数,您可能需要在所有非聚合列上分组。编辑以详细说明我的意思,即不必在group by中指定非主键(因此它不是上述问题的副本)。无需,我理解这一点。我的问题是,如果我直接从文章
表中选择,而不是从子查询中选择,我是否可以以同样的方式处理它。