【问题标题】:Nested aggregate function in PostgreSQLPostgreSQL 中的嵌套聚合函数
【发布时间】:2020-11-29 16:13:10
【问题描述】:

我正在尝试为每个article_group 返回每​​个author_idauthor_nameAVG(total) 每个author。我试图将author_idauthor_nameAVG(total) 集中到数组中。我知道这个查询会为每个数组返回一个article_group,但这很好。

我最初尝试将AVG(total)(而不是avg_total)放入我的array_agg()。这导致了一条错误消息,指出我不能有嵌套的聚合函数

我一直在想办法解决,但似乎无法解决。我尝试在WHERE 子句AS avg_total 中放置一个子查询,但没有奏效。

所以现在我尝试将AS avg_total 别名放在FROM 子句之前的独立子查询中,但它仍然不起作用。

这里是查询:

        SELECT b.article_group_id, b.article_group,
        array_agg('[' || c.author_id || ',' || c.author_name || ',' || avg_total || ']'),
        AVG((SELECT total
        FROM article f
        LEFT JOIN article_to_author w ON f.article_id = w.article_id
        LEFT JOIN author v ON w.author_id = c.author_id 
        LEFT JOIN grade z ON f.article_id = z.article_id
        ) AS avg_total)
        
        FROM article f
        LEFT JOIN article_group b ON b.article_group_id = f.article_group_id 
        LEFT JOIN article_to_author w ON f.article_id = w.article_id
        LEFT JOIN author c ON w.author_id = c.author_id 
        GROUP BY b.article_group_id, b. article_group
        

这是当前的错误信息:

    { error: syntax error at or near "AS"
    at Connection.parseE (Z:\GitFolder\roqq\server\node_modules\pg\lib\connection.js:614:13)
    at Connection.parseMessage (Z:\GitFolder\roqq\server\node_modules\pg\lib\connection.js:413:19)
    at Socket.<anonymous> (Z:\GitFolder\roqq\server\node_modules\pg\lib\connection.js:129:22)
    at Socket.emit (events.js:198:13)
    at Socket.EventEmitter.emit (domain.js:448:20)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at Socket.Readable.push (_stream_readable.js:224:10)
    at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
  name: 'error',
  length: 92,
  severity: 'ERROR',
  code: '42601',
  detail: undefined,
  hint: undefined,
  position: '430',
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'scan.l',
  line: '1149',
  routine: 'scanner_yyerror' }

这是我的桌子:

  CREATE TABLE article(
    article_id          SERIAL PRIMARY KEY,
    article_title       VARCHAR (2100),
    article_group_id    INTEGER 
);

    CREATE TABLE article_to_author(
    ata_id      SERIAL PRIMARY KEY,
    article_id  INTEGER,
    author_id   INTEGER
);

    CREATE TABLE author(
    author_id   SERIAL PRIMARY KEY,
    author_name VARCHAR(500)
);

    CREATE TABLE grade(
    grade_id       SERIAL PRIMARY KEY,
    detail         INTEGER,
    s_g            INTEGER,
    total          INTEGER,
    article_id     INTEGER
);

    CREATE TABLE article_group(
    article_group_id SERIAL PRIMARY KEY,
    article_group    VARCHAR(2100)
);

【问题讨论】:

  • 请添加一些示例数据和示例输出。这将有助于我们为您提供帮助
  • 我已经尝试过您的原始评论。我得到:错误:列“avg_total”不存在。我得到的只是错误。并且没有特定形式的数据进入。它仅返回每个 article_group 组织数组中的所有数据
  • 实际上我已经评论了语法错误。如果您发布一些数据和示例输出然后。我们可以发布正确的答案。
  • 请原谅,但我不明白您所说的“样本输出”是什么意思。我得到的所有输出都是错误。你想让我写出我期望输出的格式吗?
  • 是的。你期望的输出是什么。

标签: sql node.js postgresql average array-agg


【解决方案1】:

在您的问题中,很多事情都不清楚。根据我对您当前查询的了解,试试这个:

with cte as (
  SELECT ag.article_group_id,
         ag.article_group,
         au.author_id, 
         au.author_name, 
         avg(gr.total) as avg_total
    FROM article_group ag
         LEFT JOIN article ar on ar.article_group_id=ag.article_group_id
         LEFT JOIN article_to_author ata ON ar.article_id = ata.article_id
         LEFT JOIN author au ON ata.author_id = au.author_id 
         LEFT JOIN grade gr ON ar.article_id = gr.article_id
   GROUP BY ag.article_group_id, ag.article_group, au.author_id, au.author_name
)
SELECT article_group_id, 
       article_group,
       array_agg('[' || author_id || ',' || author_name || ',' || avg_total || ']')
  FROM cte 
 GROUP BY article_group_id, article_group

您可以在array_agg中更改任何您想要的内容

DEMO

【讨论】:

    【解决方案2】:

    我认为这是两个级别的聚合。这使您可以准确地计算总体平均值:

    SELECT article_group_id, array_agg( (author_id, author_name, avg_grade)) as authors,
           SUM(total_grade) / SUM(num_grade) as group_avg
    FROM (SELECT ag.article_group_id, au.author_id, au.author_name,
                 AVG(gr.total) as avg_grade,
                 SUM(gr.total) as total_grade,
                 COUNT(gr.total) as num_grade
          FROM article_group ag LEFT JOIN
               article ar
               ON ar.article_group_id=ag.article_group_id LEFT JOIN
               article_to_author ata
               ON ar.article_id = ata.article_id LEFT JOIN
               author au
               ON ata.author_id = au.author_id LEFT JOIN
               grade gr
               ON ar.article_id = gr.article_id
          GROUP BY ag.article_group_id, au.author_id, au.author_name
         ) a
    GROUP BY article_group_id;
    

    请注意,这会将作者聚合为 array 而不是 string。当然,如果您愿意,也可以使用字符串,但数组通常更简洁、用途更广泛。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 2020-06-29
      • 1970-01-01
      • 1970-01-01
      • 2019-12-22
      • 1970-01-01
      相关资源
      最近更新 更多