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

时间:2018-08-29 22:23:52

标签: mysql sql

在我的程序中,用户可以通过在该场所执行签到操作来在该场所赚取积分。

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

我有下表:

用户

  • id
  • 名称

场地

  • id
  • 名称

check_ins

  • id
  • user_id(FK):获得积分的用户
  • venue_id(FK):用户在其中赢得积分的场所
  • 点数:赚取的点数

奖励

  • id
  • 名称
  • venue_id:奖励所属的地点
  • 点:奖励费用金额

奖励兑换

  • id
  • user_id
  • reward_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;

然后,我可以使用一种编程语言(例如PHP)减去每个场地的剩余点数。

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

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

所以我的问题是:

  1. 是否可以在一个查询中获得总积分和全部兑换积分?
  2. 是否可以在一个查询中获得总积分,积分兑换和剩余积分?

2 个答案:

答案 0 :(得分:1)

您可以使用union allgroup 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;

可以通过减去总和轻松地计算出差异。

答案 1 :(得分:0)

您可以将两个表合并在一起。

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

必须使用左联接才能包含尚未兑换任何内容的用户。