sql—当我按键聚合时,为什么不能从“groupby”中排除依赖列?

f4t66c6m  于 2021-08-13  发布在  Java
关注(0)|答案(1)|浏览(345)

如果我有以下表(例如使用postgresql,但可以是任何其他关系数据库),其中 car 有两把钥匙( id 以及 vin ):

create table car (
  id int primary key not null,
  color varchar(10),
  brand varchar(10),
  vin char(17) unique not null
);

create table appraisal (
  id int primary key not null,
  recorded date not null,
  car_id int references car (id),
  car_vin char(17) references car (vin),
  price int
);

我可以成功地包括 c.color 以及 c.brand 因为它们依赖于 c.id :

select 
  c.id, c.color, c.brand,
  min(price) as min_appraisal,
  max(price) as max_appraisal
from car c
left join appraisal a on a.car_id = c.id
group by c.id; -- c.color, c.brand are not needed here

但是,以下查询失败,因为它不允许包含 c.color 以及 c.brand 在选择列表中,即使它确实依赖于 c.vin (那是一个键)。

select 
  c.vin, c.color, c.brand,
  min(price) as min_appraisal,
  max(price) as max_appraisal
from car c
left join appraisal a on a.car_vin = c.vin
group by c.vin; -- Why are c.color, c.brand needed here?

错误:错误:列“c.color”必须出现在GROUPBY子句中,或用于聚合函数位置:18
db fiddle中的示例。

oewdyzsn

oewdyzsn1#

因为只有pk覆盖了 GROUP BY 条款。因此,您的第一个查询是有效的。一 UNIQUE 约束不存在。
不可延期的 UNIQUE 和一个 NOT NULL 约束也可以限定。但这并没有实现——以及sql标准已知的一些其他函数依赖关系。该功能的主要作者peter eisentrat有更多的想法,但当时确定需求很低,相关成本可能很高。请参阅关于pgsql的特性的讨论。
手册:
什么时候 GROUP BY 如果存在,或存在任何聚合函数,则对无效 SELECT 列出引用未分组列的表达式,除非在聚合函数中或未分组列在功能上依赖于已分组列,否则未分组列可能返回多个值。如果分组列(或其子集)是包含未分组列的表的主键,则存在函数依赖关系。
更明确地说:
postgresql识别函数依赖关系(允许从 GROUP BY )仅当表的主键包含在 GROUP BY 列表。sql标准指定了应该识别的附加条件。
c.vinUNIQUE NOT NULL ,您可以改为使用pk列来修复第二个查询:

...
group by c.id;

另外,当引用完整性被强制执行并查询整个表时,两个给定的查询都可以便宜得多:在 appraisal 在加入之前。这样就不需要 GROUP BY 在外面 SELECT 先验的。比如:

SELECT c.vin, c.color, c.brand
     , a.min_appraisal
     , a.max_appraisal
FROM   car c
LEFT   JOIN (
   SELECT car_vin
        , min(price) AS min_appraisal
        , max(price) AS max_appraisal
   FROM   appraisal
   GROUP  BY car_vin
   ) a ON a.car_vin = c.vin;

请参见:
一个查询中有多个array\u agg()调用
相关:
sql语句在mysql中工作在postgresql中不工作-sum&group\u by rails 3
postgresql-group by子句

相关问题