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

多表查询方案:筛选无游玩记录、合规统计值的非封禁玩家

最优SQL查询方案:筛选符合条件的玩家

首先我先明确你的需求细节,确保理解到位:

  • 从player表中筛选玩家,需同时满足:
    1. 从未进行过游戏:该玩家在player_log表中无任何活动记录(默认游戏行为会被写入player_log)
    2. 统计值不超指定阈值:若玩家在player_stat有记录,其stat值必须≤设定阈值;无player_stat记录的玩家也符合条件(毕竟从未玩过游戏可能没有统计数据)
    3. 排除特定用户:排除已被封禁1天的用户$uid(默认同时排除所有封禁1天的玩家,若你只想排除$uid这个特定账号,可随时调整条件)

最优查询语句

假设:

  • player.status字段中,'ban_1d'代表“封禁1天”的状态(你可替换为实际状态值,比如数值1)
  • 阈值用@threshold表示(替换为实际数值,比如100)
  • 各关联字段(player.id、player_log.srl、player_stat.srl)已建立索引
SELECT p.*
FROM player p
-- 排除封禁1天的玩家及指定$uid
WHERE p.status != 'ban_1d'
  AND p.id != $uid
-- 从未进行过游戏:player_log中无该玩家记录
  AND NOT EXISTS (
    SELECT 1
    FROM player_log pl
    WHERE pl.srl = p.id
  )
-- 统计值符合要求:要么无stat记录,要么stat≤阈值
  AND (
    NOT EXISTS (
      SELECT 1
      FROM player_stat ps
      WHERE ps.srl = p.id
    )
    OR EXISTS (
      SELECT 1
      FROM player_stat ps
      WHERE ps.srl = p.id
        AND ps.stat <= @threshold
    )
  );

为什么这是最优方案?

  1. 用NOT EXISTS替代LEFT JOIN ... IS NULL:
    数据库优化器对NOT EXISTS的处理效率更高,它找到第一条匹配记录后就会停止查询,避免全表扫描。尤其是当关联字段有索引时,性能提升会非常明显。

  2. 逻辑拆分更清晰:
    把“无stat记录”和“stat≤阈值”拆分为OR条件,既符合需求逻辑,又利用了子查询的短路特性,减少不必要的计算。

  3. 避免结果集膨胀:
    如果用LEFT JOIN关联player_stat,若一个玩家有多条stat记录,会产生重复的玩家数据;而EXISTS子查询只判断存在性,不会导致结果集冗余。


可选调整(根据实际需求)

  • 若仅需排除$uid特定用户(不管其是否封禁),可去掉p.status != 'ban_1d'条件,只保留p.id != $uid。
  • 若要求玩家必须有stat记录且≤阈值,可删除NOT EXISTS (...)部分,只保留EXISTS (SELECT 1 FROM player_stat ps WHERE ps.srl = p.id AND ps.stat <= @threshold)。
  • 若要进一步优化性能,建议给player_stat建立联合索引(srl, stat),这样判断stat≤阈值时可直接使用索引,无需回表查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:38:37