这是我的查询:
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子句中或用于聚合函数LINE 1:SELECT autor.entwickler FROM autor left join anwendung on a ...
我完全理解错误,并假设mysql实现比postgres实现更少SQL . 但是我怎样才能得到理想的结果呢?
2 回答
PostgreSQL当前不允许含糊不清的
GROUP BY
语句,其结果取决于扫描表的顺序,使用的计划等 . 标准表示它应该如何工作AFAIK,但是一些数据库(如5.7之前的MySQL版本)允许更宽松的查询,只选择出现在SELECT
列表但不在GROUP BY
中的元素遇到的第一个值 .在PostgreSQL中,您应该使用DISTINCT ON进行此类查询 .
你想写下这样的东西:
(根据后续评论更正的语法)
这有点像MySQL 5.7的
ANY_VALUE(...)
group by
的伪函数,但反过来 - 它表示distinct on
子句中的值必须是唯一的,并且任何值都可以接受未指定的列 .除非有
ORDER BY
,否则没有保证选择了哪些值 . 您通常应该有ORDER BY
的可预测性 .还注意到使用像
min()
或max()
这样的聚合会起作用 . 虽然这是真的 - 并且将导致可靠和可预测的结果,不像使用DISTINCT ON
或一个ambigiousGROUP BY
- 由于需要额外的排序或聚合而具有性能成本,并且它仅适用于序数据类型 .Craig的答案和你在评论中得到的查询共享相同的缺陷:表
anwendung
位于 right side of a LEFT JOIN ,这与你明显的意图相矛盾 . 你关心anwendung.name
并选择autor.entwickler
arbitrarily . 我会再回到那里了 .它应该是:
DISTINCT ON(1)只是DISTINCT ON(an.name)的语法简写 . 这里允许进行位置参考 .
如果某个应用程序(
anwendung
)有多个开发人员(entwickler
),则会选择一个开发人员 arbitrarily . 如果你想要"first"(按字母顺序根据你的语言环境),你必须添加一个ORDER BY
子句:正如@mdahlman暗示的那样,一种更规范的方式是:
或者,更好的是,清理数据模型,正确实现
anwendung
和_1015128之间的 n:m relationship ,添加代理主键为anwendung
和autor
几乎不是唯一的,使用外键约束强制关系完整性并调整生成的查询:正确的方法
此查询每个应用程序检索一行,其中一个关联作者(按字母顺序排列第一个)或如果没有则检索NULL:
结果: