Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从子查询中选择,而不必指定分组依据中的所有列_Sql_Postgresql_Group By - Fatal编程技术网

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中指定非主键(因此它不是上述问题的副本)。无需,我理解这一点。我的问题是,如果我直接从
文章
表中选择,而不是从子查询中选择,我是否可以以同样的方式处理它。