对行总和的约束

Posted

技术标签:

【中文标题】对行总和的约束【英文标题】:Constraint on sum from rows 【发布时间】:2016-05-09 13:20:44 【问题描述】:

我在 PostgreSQL 9.4 中有一张表:

user_votes (
  user_id int,
  portfolio_id int,
  car_id int
  vote int
)

是否可以在表格上设置一个约束,以便用户在每个投资组合中最多可以有 99 个点进行投票? 这意味着一个用户可以拥有多行,其中包含相同的 user_id 和 portfolio_id,但不同的 car_id 和 vote。总票数不应超过 99,但可以放在不同的汽车之间。

这样做:

INSERT INTO user_vores (user_id, portfolio_id, car_id, vote) VALUES
    (1, 1, 1, 20),
    (1, 1, 7, 40),
    (1, 1, 9, 25)

都可以,但是当尝试添加超过 99 票的内容时应该会失败,比如另一行:

    INSERT INTO user_vores (user_id, portfolio_id, car_id, vote) VALUES
    (1, 1, 21, 40)

【问题讨论】:

【参考方案1】:

很遗憾,如果您尝试创建这样的constraint,您将看到以下错误消息:

ERROR: aggregate functions are not allowed in check constraints

但关于 postgresql 的奇妙之处在于,总是有不止一种方法可以给猫剥皮。您可以使用 BEFORE trigger 来检查您尝试插入的数据是否满足我们的要求。

BEFORE 触发的行级触发器可以返回 null 来表示触发器 经理跳过该行的其余操作(即, 随后的触发器不会被触发,并且 INSERT/UPDATE/DELETE 会 此行不会发生)。如果返回非空值,则 操作继续该行值。

在您的触发器中,您将计算投票数

 SELECT COUNT(*) into vote_count FROM user_votes WHERE user_id = NEW.user_id

现在如果 vote_count 是 99 你返回 NULL 并且数据不会被插入。

【讨论】:

以上是关于对行总和的约束的主要内容,如果未能解决你的问题,请参考以下文章

用scikit学习线性模型约束系数总和

BZOJ1458: 士兵占领

如何在ortools python中设置约束

Django:将价格注释到行,然后按字段对行进行分组,并将价格总和注释到组

具有最小尺寸约束的聚类算法

Python中的约束最小二乘估计