我想获取每个奖金(bonus_records.uid - 唯一 ID)的最后更新(max(bonus_records.id))然后满足以下条件:
- 从未被指定玩家兑换过
- 已被指定玩家兑换但兑换次数少于redeem_count 超过
- 在上述时刻兑换并激活的奖金(是字段为 completed 和 canceled 为 0 的奖金)
附加信息:如果redeem_count等于0,则表示该赠金没有兑换限额
这是数据库的基本结构:
DB-FIDDLE v2 (With @Solarflare query)
我的查询失败:
SELECT MAX(br1.id) /* Get last update of bonus */,
br1.uid,
br1.name,
rb1.instance_id,
rb1.player_id,
br1.redeem_count,
rb1.executed,
rb1.completed,
rb1.canceled
FROM
bonus_records br1
LEFT JOIN
redeemed_bonuses rb1 ON
rb1.bonus_id = br1.id
WHERE
(rb1.player_id IS NULL) OR /* never redeemed */
(rb1.player_id = 1 AND /* if redeemed then */
(
br1.redeem_count > ( /* total count of X redemed bonus is less then redeem_count but redeem_count <> 0 */
SELECT COUNT(*)
FROM redeemed_bonuses rb2
INNER JOIN bonus_records br2 ON rb2.bonus_id = br2.id
WHERE br2.uid = br1.uid AND rb2.completed = 0 AND rb2.canceled = 0
) OR
br1.redeem_count = 0 /* redeem_count = 0 means that there is no established limit of redeem */
)
)
GROUP BY
br1.uid
预期结果:
如果我有这个奖励列表:
和这个兑换的奖金列表:
那么 player_id = 1 的预期结果奖励列表将是:
最佳答案
您的查询/逻辑中存在一些问题:
select max(id), name, ... group by uid
将不为您提供具有最大 id 的行。它将为您提供最大 ID 以及该组中任何 行的值。如果每组只有一行(例如,如果 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
如果有 any 玩家兑换了此 bonusid,则该值为 false。如果您将 playerid 包含在on
条件中,则如果玩家不会为给定的uid
兑换所有不同的 id,则为真(这可能是不可能的)。自从您通过
rb1.bonus_id = br1.id
加入
并将您的条件应用于此id
(但不是uid
):如果有一些旧条目具有更大的redeem_count
,即使有一个最新的 id 具有较低的redeem_count
,它也会评估为 true >(这不会成为group by
的一部分,因为您将其过滤掉了)。相反,您可能需要在
left join
之后应用过滤器,例如使用group by ... having ...
或select ...来自(选择...分组依据...)其中...
话虽如此,我不会修复您的查询(尽管它可能是可以挽救的),但会为您写一个具有新结构的新查询。
将其分解为多个步骤,首先,获取所有有效奖金的列表:
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
关于mysql - 获取表A中的所有记录,如果满足表B的条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56117372/