SQL 每组选择第一条记录

SQL selecting first record per group

我有一个 table 看起来像这样:

CREATE TABLE UTable (
    m_id        TEXT PRIMARY KEY,
    u1          TEXT,
    u2          TEXT,
    u3          TEXT,
    -- other stuff, as well as
    gid         INTEGER,
    gt          TEXT,
    d           TEXT,
    timestamp   TIMESTAMP
);

CREATE TABLE OTable (
    gid         INTEGER,
    gt          TEXT,
    d           TEXT,
    -- other stuff, such as
    n           INTEGER
);
CREATE UNIQUE INDEX OTable_idx ON OTable (gid, gt, d);

对于OTable中的每条符合条件的记录(gid, gt的固定值),我想加入UTable中具有最小时间戳的相应记录。

吸引我的是在我的最终结果中我不关心时间戳,我显然需要在 d 上分组(因为 gidgt 是固定的) ,但我 需要从 selected 记录中提取 u1, u2, u3

SELECT o.d, u.u1, u.u2, u.u3, o.n
    FROM UTable u
INNER JOIN OTable o
  ON u.gid = o.gid AND u.gt = o.gt AND u.d = o.d
WHERE u.gid = 3 AND u.gt = 'dog night'
GROUP BY u.d
-- and u.timestamp is the minimum for each group
;

我认为我的第一步应该只是在 UTable 上做 select 然后我可以加入反对。但即使在那里我也有点困惑。

SELECT u.d, u.u1, u.u2, u.u3
    FROM UTable u
WHERE u.gid = 3 AND u.gt = 'dog night';

我想添加 HAVING MIN(u.timestamp),但这无效。

关于我需要做什么的任何指示?

我确实看到了 this question,但这并不是我所需要的,因为我无法对所有 UTable 值进行分组,以免我 select 太多东西。

GROUP BY u.d(未同时列出 u1u2u3)仅在 u.dPRIMARY KEY(其中它不是,在您的场景中也没有意义)。参见:

  • Is it possible to have an SQL query that uses AGG functions in this way?

我建议在 UTable 的子查询中使用 DISTINCT ON

SELECT o.d, u.u1, u.u2, u.u3, o.n
FROM  (
   SELECT DISTINCT ON (u.d)
          u.d, u.u1, u.u2, u.u3
   FROM   UTable u
   WHERE  u.gid = 3
   AND    u.gt = 'dog night'
   ORDER  BY u.d, u.timestamp
   ) u
JOIN   OTable o USING (gid, gt, d);

参见:

  • Select first row in each GROUP BY group?

如果 UTable 很大,建议至少在 (gid, gt) 上使用多列索引。 OTable.
相同 甚至可能 (gid, gt, d)。取决于数据类型、基数、...