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

时间:2019-03-24 07:55:12

标签: postgresql postgresql-9.5

在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条记录(上面的插入语句中的所有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子句必须为:

  

按发票ID,物料ID,仓库ID分组

1 个答案:

答案 0 :(得分:4)

这是因为您将invoice_id, item_id定义为表的主键,并且按唯一键分组就足够了,因为向组中添加更多列不会改变组的依据。

Quote from the manual

  

存在GROUP BY或存在任何聚合函数时,SELECT列表表达式引用聚合组中的非分组列是无效的,或者非分组列在功能上取决于分组列< / strong>,因为对于未分组的列,否则将有多个可能的值返回。如果分组的列(或其子集)是包含未分组的列的表的主键,则存在功能依赖性。

(重点是我的)

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