代码之家  ›  专栏  ›  技术社区  ›  Yahya Uddin

从SQL(MySQL)中的两个不同表中减去计算值

  •  -1
  • Yahya Uddin  · 技术社区  · 6 年前

    在我的程序中,用户可以通过在某个地点执行签入来赚取积分。

    然后,他们可以使用这些积分在该地点兑换奖励。积分不可跨场馆共享。

    用户

    • 身份证件
    • 名称

    场馆

    签入

    • user\u id(FK):获得积分的用户

    奖励

    • 身份证件
    • 名称
    • 地点\u id:奖励所属的地点
    • 积分:奖励成本的金额

    • 身份证件
    • 奖励id

    select venue_id, sum(points) as total_points
    from check_ins
    WHERE user_id = 109
    group by venue_id, user_id;
    

    我可以这样计算按地点兑换的点数:

    select venue_id, sum(points) as points_redeemed
    from reward_redemptions
    JOIN rewards on reward_redemptions.reward_id = rewards.id
    GROUP BY venue_id;
    

    但是,我希望使用SQL来实现这一点(最好是在一个查询中,以减少在查询之间更改数据的机会,使代码更简单,并可能提高性能)。理想的最终结果是:

    venue_id    total_points    points_redeemed     points_remaining      
    #5          10              2                   8
    #15         25              10                  15
    #189        150             20                  130
    

    1. 是否可以在一次查询中获得全部积分和兑换的积分?
    2. 是否可以在一次查询中获得总积分、兑换积分和剩余积分?
    2 回复  |  直到 6 年前
        1
  •  1
  •   Gordon Linoff    6 年前

    你可以用 union all group by . 以下是关于场馆和积分的查询:

    select venue_id, sum(total_points) as total_points,
           sum(points_redeemed) as points_redeemed
    from ((select venue_id, sum(points) as total_points, 0 as points_redeemed
           from check_ins
           group by venue_id
          )
          union all
          (select venue_id, 0 as total_points, sum(points) as points_redeemed
           from reward_redemptions rr join
                rewards r
                on rr.reward_id = r.id
           group by venue_id
          )
         ) p
    group by venue_id;
    

    通过减去总和,可以很容易地计算出差值。

        2
  •  0
  •   Barmar    6 年前

    SELECT c.venue_id, c.user_id
            SUM(c.points) AS total_points, 
            IFNULL(r.points_redeemed, 0) AS points_redeemed, 
            SUM(c.points) - IFNULL(r.points_redeemed, 0) AS points_remaining
    FROM check_ins AS c
    LEFT JOIN (
        select venue_id, user_id, sum(points) as points_redeemed
        from reward_redemptions
        JOIN rewards on reward_redemptions.reward_id = rewards.id
        GROUP BY venue_id, user_id) AS r
    ON c.venue_id = r.venue_id AND c.user_id = r.user_id
    GROUP BY c.venue_id, c.user_id
    

    左联接对于包含尚未兑换任何东西的用户是必需的。