使用Postgres聚合函数在每个GROUP BY组中选择第一行?

时间:2016-11-16 09:00:23

标签: sql postgresql

我有两个表:user用于跟踪用户信息,users_classes用于跟踪用户和类之间的关系(类在单独的表中)。我想加入表格并返回用户的信息以及他们所在的一系列课程。有没有一种有效的方法可以这样做?

表格结构:

CREATE TABLE users (
  id        BIGSERIAL PRIMARY KEY,
  username  VARCHAR(255) UNIQUE,
  email     VARCHAR(255) NOT NULL UNIQUE
)

CREATE TABLE users_classes (
  user_id   BIGINT REFERENCES users(id),
  class_id  BIGINT REFERENCES classes(id),
  PRIMARY KEY(user_id, class_id)
)

我的尝试:

SELECT
  u.id,
  FIRST(u.username) AS username,
  FIRST(u.email) AS email,
  array_agg(c.class_id) AS classes
FROM users_classes AS c
JOIN users AS u
ON c.user_id = u.id
GROUP BY u.id;

我认为这可行(在实施FIRST()之后),但有更标准的方法吗?

2 个答案:

答案 0 :(得分:0)

只需将// Paste this snippet in the beginning of your method if (InvokeRequired) { this.Invoke(new MethodInvoker(/*Enter the name of your method here*/)); return; } // Method code goes here ...... /* Example: private void SomeMethod(object sender, EventArgs e) { if (InvokeRequired) { this.Invoke(new MethodInvoker(SomeMethod)); // Name of current method is 'SomeMethod' return; } // Code continues here int x,y,z; // Do something ..... } */ 子句的列添加为:

GROUP BY

答案 1 :(得分:0)

Postgres 要求您指定如何在组中拾取行投影,因此您必须为每个选择投影指定一个聚合函数。

您可以使用 mode() 选择组中的第一行/最后一行。以下是基于您的问题的示例:

SELECT
  mode() WITHIN GROUP (ORDER BY u.id) as userId,
  mode() WITHIN GROUP (ORDER BY u.username DESC) as username, -- pick last username
  mode() WITHIN GROUP (ORDER BY u.email) as email,
  array_agg(c.class_id) AS classes
FROM users_classes AS c
JOIN users AS u
ON c.user_id = u.id
GROUP BY u.id;