如果满足表B的条件,则获取表A中的所有记录

时间:2019-05-13 17:39:47

标签: mysql select

我想获取每个奖金( bonus_records.uid-唯一ID )的最新更新( max(bonus_records.id)),然后满足以下条件:

  1. 从未被指定玩家赎回的
  2. 已被指定玩家兑换的
  3. 但兑换次数少于 redeem_count 超出
  4. 在此刻赎回并激活的奖金(是在字段完成取消为0的奖金)

其他信息::如果redeem_count等于0,则该奖励没有兑换限制

这是数据库的基本结构:

enter image description here

DB-FIDDLE

DB-FIDDLE v2 (With @Solarflare query)

DB-FIDDLE v3

我的查询失败:

android:layerType="software"

预期结果:

如果我有此奖金列表:

enter image description here

这是兑换的奖金列表:

enter image description here

然后,player_id = 1的预期结果奖金列表将为:

enter image description here

1 个答案:

答案 0 :(得分:1)

您的查询/逻辑中存在一些问题:

  • select max(id), name, ... group by uid为您提供具有最大ID的行。它将为您提供最大的id,以及该组中 any 行的值。如果每个组只有一行(例如,如果uid是唯一的/主键),则可能是您要寻找的那一行,否则,它不确定(并且对于MySQL 5.7失败),请参见MySQL Handling of GROUP BY以及关于stackoverflow的有关sql_mode=only_full_group_by错误消息的任何问题。

  • 如果有任何名玩家兑换了此红利,
  • left join ... ON bonus_id = id where rb1.player_id IS NULL将为假。如果您在on条件中加入了玩家ID,那么如果玩家没有为给定的uid兑换 all 个不同的ID,那将是正确的(可能是不可能的)

  • 类似的情况发生,因为您通过join rb1.bonus_id = br1.id并将条件应用于此id(但没有uid):如果有一些旧条目较大的redeem_count,即使有一个最新的ID且其redeem_count较低,它也会计算为true(因为您将其过滤掉,所以它不属于group by)。< / p>

  • 相反,您可能需要在left join之后应用过滤器,例如使用group by ... having ...select ... from (select ... group by ...) where ...

话虽如此,我不会修复您的查询(尽管它可以挽救您的问题),但会为您编写一个具有新结构的新查询。

将其分解为多个步骤,首先,获取所有有效奖金的列表:

select * from bonus_records br
where not exists 
  (select 1 from bonus_records br1
   where br1.uid = br.uid and br1.id > br.id);

下一步是检查特定玩家赎回特定uid的频率(通过检查uid表获得bonus_records信息):

select br.uid, count(*) 
from redeemed_bonuses rb
join bonus_records br on br.id = rb.bonus_id
where rb.player_id = 1
   and not (rb.completed = 0 and rb.canceled = 0) 
group by br.uid;

根据评论,条件not (rb.completed = 0 and rb.canceled = 0)足以满足要求。

现在加入这两个位置,并应用有关实际计数低于redeem_count的条件:

select pb.*, rd.actual_count from 
  (select * from bonus_records br
   where not exists 
     (select 1 from bonus_records br1
      where br1.uid = br.uid and br1.id > br.id)
  ) pb -- active potential bonuses
left join  
  (select br.uid, count(*) as actual_count 
   from redeemed_bonuses rb
   join bonus_records br on br.id = rb.bonus_id
   where rb.player_id = 1
      and not (rb.completed = 0 and rb.canceled = 0) 
   group by br.uid
  ) rd -- redeemed bonuses by that user
on pb.uid = rd.uid 
where rd.actual_count is null            -- uid never redeemed (left join empty)
   or rd.actual_count < pb.redeem_count  -- still some remaining
   or pb.redeem_count = 0                -- unlimited bonus