首页 > 解决方案 > 使用 HAVING 根据 Sequelize Postgres 中嵌套模型的总和进行过滤

问题描述

我在 Postgres 中有一个数据结构,如下所示:

捐款

id  amount  status
1   5000    OK
2   7500    OK

捐赠物品

id  donationId  amount  includeInTotals
1   1           2500    false
2   1           2500    false
3   2           7500    false

在伪 SQL 中,我正在尝试执行以下操作:

SELECT * FROM donations WHERE SUM(SELECT donation.items WHERE "donationId" = "donations"."id" AND "includeInTotals" = false) >= "donations"."amount"

本质上是要删除“includeInTotals = false”捐赠项目的总数与捐赠价值相同的捐赠。

这是迄今为止我为 Sequelize 获得的代码:

Models.donations.findAndCountAll({
   where: { status: 'OK' },
   include: {
        model: Models.donation_items,
        as: 'items',
        duplicating: false,
    },
   having: sequelize.literal('COALESCE(SUM(CASE WHEN "items"."includeInTotals" = false THEN items.amount ELSE 0 END), 0) < "donations"."amount"'),
   group: ['"donations.id"', '"items.id"']
});

这适用于捐赠 ID: 2 – 它不是由查询返回的,但捐赠 ID: 1是,尽管两个金额等于 5000。

我用 SUM 做错了什么吗?

标签: node.jspostgresqlsequelize.js

解决方案


我可以提供一个应该有效的实际查询,这是答案的一半:

SELECT d1.*
FROM Donations d1
LEFT JOIN
(
    SELECT donationId, SUM(amount) AS amount
    FROM DonationItems di
    WHERE includeInTotals = false
    GROUP BY donationId
) d2
    ON d1.id = d2.donationId AND d1.amount = d2.amount
WHERE
    d2.donationId IS NULL;

虽然这不会触及您的 Sequelize 问题,但拥有正确的原始查询是在 PHP 中做任何事情的总先决条件,这将在以后取得成果。还有其他更有效的方法可以编写此查询,但上述版本可能最容易集成到您的 PHP 代码中。


推荐阅读