postgres 查询根据某些列的多个副本获取第一行

use*_*298 3 sql postgresql greatest-n-per-group postgresql-9.1

假设我有一张桌子 -

A        B       C  
1        3       5  
1        3       7  
1        3       9  
2        4       3  
2        4       6  
2        4       1 
Run Code Online (Sandbox Code Playgroud)

这里有 A 和 B 的相同组合的多个副本。对于每个组合,我想要回它的第一个条目。所以我想要这个表的结果是-

A        B      C  
1        3      5  
2        4      3 
Run Code Online (Sandbox Code Playgroud)

我怎样才能在 postgres sql 中做到这一点?

Cra*_*ger 9

假设您可以根据您想要的 a、b 和 c 的排序来定义“第一个” DISTINCT ON

SELECT
  DISTINCT ON ("A", "B")
  "A", "B", "C"
FROM Table1
ORDER BY "A", "B", "C";
Run Code Online (Sandbox Code Playgroud)

例如http://sqlfiddle.com/#!15/9ca16/1

请参阅SELECT参考资料 获取更多信息DISTINCT ON


如果您犯了假设 SQL 表具有固有顺序的严重错误,那么您将需要在继续之前修复您的表。您可以使用 PostgreSQLctid伪列来指导创建与当前磁盘表顺序匹配的主键。应该安全地:

ALTER TABLE mytable ADD COLUMN id SERIAL PRIMARY KEY;
Run Code Online (Sandbox Code Playgroud)

因为 PostgreSQL 倾向于按表顺序写入键。这是不能保证的,但是当没有主键时,也不能保证其他任何事情。然后你可以:

SELECT
  DISTINCT ON ("A", "B")
  "A", "B", "C"
FROM Table1
ORDER BY id;
Run Code Online (Sandbox Code Playgroud)

(编辑:我不建议ctid在应用程序中的查询中使用它。它是解决特定问题的便捷工具,但它并不是 PostgreSQL 中真正的公共 API,也不是 SQL 标准的一部分。它不像ROWIDOracle 中那样,它会改变由于真空等原因。PostgreSQL 在未来版本中可以随意破坏/更改/删除它。)