You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用Postgres自动计算Supabase饮食表的营养统计值?

Postgres自动维护饮食日统计值的解决方案

方案1:用视图实时计算(推荐)

直接创建视图替代days_of_diet表中的统计字段,完全不需要手动维护,数据永远和meals表同步:

CREATE VIEW days_of_diet_stats AS
SELECT
    d.id, -- 假设days_of_diet有主键id
    d.meal_ids,
    COALESCE(SUM(m.calories), 0) AS total_calories,
    COALESCE(SUM(m.protein), 0) AS total_protein,
    COALESCE(SUM(m.carbs), 0) AS total_carbs,
    -- 保留days_of_diet的其他字段
    d.other_fields
FROM days_of_diet d
LEFT JOIN meals m ON m.id = ANY(d.meal_ids)
GROUP BY d.id, d.meal_ids, d.other_fields;

优势

  • 无冗余数据,彻底避免数据不一致问题
  • 无需编写触发器或后端逻辑,Postgres自动实时计算
  • Supabase中可直接查询该视图,使用方式与普通表完全一致

方案2:用触发器维护表中存储的统计值

如果必须将统计值存在days_of_diet表中(比如需要为统计字段创建索引优化查询性能),可以通过触发器自动更新:

步骤1:创建更新统计值的函数

CREATE OR REPLACE FUNCTION update_diet_day_totals()
RETURNS TRIGGER AS $$
BEGIN
    -- 更新当前饮食日的统计值
    UPDATE days_of_diet
    SET
        total_calories = (SELECT COALESCE(SUM(calories), 0) FROM meals WHERE id = ANY(meal_ids)),
        total_protein = (SELECT COALESCE(SUM(protein), 0) FROM meals WHERE id = ANY(meal_ids)),
        total_carbs = (SELECT COALESCE(SUM(carbs), 0) FROM meals WHERE id = ANY(meal_ids))
    WHERE id = NEW.id;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

步骤2:为days_of_diet表添加触发器(餐食ID数组变化时触发)

CREATE TRIGGER trigger_diet_day_meal_ids_change
AFTER INSERT OR UPDATE OF meal_ids ON days_of_diet
FOR EACH ROW
EXECUTE FUNCTION update_diet_day_totals();

步骤3:为meals表添加触发器(营养数值变化时触发)

CREATE OR REPLACE FUNCTION update_related_diet_days()
RETURNS TRIGGER AS $$
BEGIN
    -- 找到所有包含当前餐食ID的饮食日记录并更新
    UPDATE days_of_diet
    SET
        total_calories = (SELECT COALESCE(SUM(calories), 0) FROM meals WHERE id = ANY(meal_ids)),
        total_protein = (SELECT COALESCE(SUM(protein), 0) FROM meals WHERE id = ANY(meal_ids)),
        total_carbs = (SELECT COALESCE(SUM(carbs), 0) FROM meals WHERE id = ANY(meal_ids))
    WHERE OLD.id = ANY(meal_ids);

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_meal_nutrition_change
AFTER UPDATE OF calories, protein, carbs ON meals
FOR EACH ROW
EXECUTE FUNCTION update_related_diet_days();

补充:处理餐食删除场景

若需要支持删除餐食后自动更新统计值,给meals表添加删除触发器:

CREATE TRIGGER trigger_meal_delete
AFTER DELETE ON meals
FOR EACH ROW
EXECUTE FUNCTION update_related_diet_days();

选择建议

  • 若查询频率高、对实时性要求高,优先选视图方案,架构更简洁易维护
  • 若需要对统计字段创建索引或有极高的查询性能要求,再用触发器方案,但要注意触发器会增加写操作的开销

内容的提问来源于stack exchange,提问作者flicknba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 21:10:28