一尘不染

消除PostgreSQL SELECT语句中的重复行

sql

这是我的查询:

SELECT autor.entwickler,anwendung.name
  FROM autor 
  left join anwendung
    on anwendung.name = autor.anwendung;

 entwickler |    name     
------------+-------------
 Benutzer 1 | Anwendung 1
 Benutzer 2 | Anwendung 1
 Benutzer 2 | Anwendung 2
 Benutzer 1 | Anwendung 3
 Benutzer 1 | Anwendung 4
 Benutzer 2 | Anwendung 4
(6 rows)

我想为该字段中的每个不同值保留一行name,并像这样丢弃其他值:

 entwickler |    name     
------------+-------------
 Benutzer 1 | Anwendung 1
 Benutzer 2 | Anwendung 2
 Benutzer 1 | Anwendung 3
 Benutzer 1 | Anwendung 4

在MySQL中,我只会做:

SELECT autor.entwickler,anwendung.name
  FROM autor
  left join anwendung
    on anwendung.name = autor.anwendung
 GROUP BY anwendung.name;

但是PostgreSQL给我这个错误:

错误:“ autor.entwickler”列必须出现在GROUP BY子句中或在聚合函数中使用第1行:SELECT autor.entwickler
FROM autor左加入anwendung …

我完全理解该错误,并假设mysql实现比postgres实现更不符合SQL。但是我怎样才能得到理想的结果呢?


阅读 233

收藏
2021-03-17

共1个答案

一尘不染

PostgreSQL当前不允许模棱两可的GROUP BY语句,其结果取决于表的扫描顺序,使用的计划等。这就是标准说它应该在AFAIK中起作用的方式,但是某些数据库(例如5.7之前的MySQL版本)允许松散的语句。这些查询仅选择出现在SELECT列表中但不在中的元素遇到的第一个值GROUP BY

在PostgreSQL中,您应该使用DISTINCT ON这种查询。

您想要编写类似以下内容的内容:

SELECT DISTINCT ON (anwendung.name) anwendung.name, autor.entwickler
FROM author 
left join anwendung on anwendung.name = autor.anwendung;

(根据后续评论更正了语法)

这有点像MySQL 5.7的ANY_VALUE(...)伪函数group by,但是反过来-它表示distinct on子句中的值必须是唯一的,并且对于 指定的列,任何值都是可接受的。

除非有ORDER BY,否则没有保证选择哪个值。通常,您应该具有ORDER BY可预测性。

还需要注意的是,使用类似min()或的聚合是max()可行的。尽管确实如此-与使用DISTINCT ON或模棱两可的方法不同GROUPBY,它会导致可靠和可预测的结果-但由于需要额外的排序或聚合,因此会降低性能,并且仅适用于顺序数据类型。

2021-03-17