PostgreSQL是否会自动检测group by子句中的唯一记录?

问题描述 投票:0回答:1

PostgreSQL中是否强制要求在group by子句中添加唯一列?

我通常使用Microsoft SQL Server,我们必须在group by子句中添加所有需要的列。

PostgreSQL查询:

DROP TABLE IF EXISTS temp_invoice_detail;
CREATE TEMP TABLE temp_invoice_detail(
    invoice_id integer,
    item_id integer,
    qty integer,
    warehouse_id integer    
);

ALTER TABLE temp_invoice_detail ADD CONSTRAINT temp_invoice_detail_result_pkey PRIMARY KEY (invoice_id, item_id);

insert into temp_invoice_detail (invoice_id, item_id, qty, warehouse_id) values (1, 1, 100, 1);
insert into temp_invoice_detail (invoice_id, item_id, qty, warehouse_id) values (1, 2, 200, 1);
insert into temp_invoice_detail (invoice_id, item_id, qty, warehouse_id) values (2, 1, 100, 1);

select invoice_id, item_id, sum(qty) as total_qty, warehouse_id
from temp_invoice_detail
group by invoice_id, item_id --should I add "warehouse_id" in group by clause?
order by invoice_id, item_id;

DROP TABLE IF EXISTS temp_invoice_detail;

我希望PostgreSQL显示错误信息:

列“temp_invoice_detail.warehouse_id”必须出现在GROUP BY子句中或用于聚合函数

但查询成功运行并返回3条记录(上面的insert语句中的所有3条记录)。

invoice_id  item_id  total_qty  warehouse_id
1           1        100        1
1           2        200        1
2           1        100        1

在MS-SQL中,对于此查询可以无错误地运行,group by子句必须是:

group by invoice_id,item_id,warehouse_id

postgresql postgresql-9.5
1个回答
4
投票

这是因为您将invoice_id, item_id定义为表的主键,并且通过唯一键进行分组就足够了,因为向该组添加更多列不会更改该组的结果。

Quote from the manual

当存在GROUP BY或存在任何聚合函数时,SELECT列表表达式无法引用未聚合的列,但聚合函数内或未分组的列在功能上依赖于分组列,因为否则会有更多比未归属列返回的一个可能值。如果分组列(或其子集)是包含未分组列的表的主键,则存在功能依赖性

(强调我的)

这实际上是SQL标准允许的。 Postgres甚至可以从组中删除不需要的列(基于主键或唯一键的存在),因为这样可以提高性能。

© www.soinside.com 2019 - 2024. All rights reserved.