【问题标题】:Excluding records between tables排除表之间的记录
【发布时间】:2016-04-08 09:38:07
【问题描述】:

查看下表。

spawns:

+----------+---+----+----+--+
| id_spawn | position | map |
+----------+---+----+----+--+
|        1 |        1 |   1 |
|        2 |        2 |   1 |
+----------+----------+-----+

games;

+---------+-----+
| id_game | map |
+---------+-----+
|       1 |   1 |
|       2 |   1 |
|       3 |   1 |
|       4 |   1 |
|       5 |   1 |
+---------+-----+

warriors

+---------+------+----------+
| id_join | game | position |
+---------+------+----------+
|       1 |    1 |        2 |
+---------+------+----------+

我正在尝试从spawns 中获取尚未在warriors 中使用的position,并给出特定的game。第一次尝试我做了:

select s.position
from spawns s
left join games g on g.map = s.map
left join warriors w on w.game = g.id_game
where s.position not in(w.position)
and g.id_game = 1;

查询按预期返回1

但是,对于game = 5,我期待有 2 个可用职位,但收到的结果为空。我假设数据库引擎没有找到gameswarriors 之间的关系,因为游戏没有战士可以比较。那么,我怎样才能获得这些职位呢?

【问题讨论】:

  • 也许我遗漏了什么,但我没有在表格中看到s.game
  • 谢谢。抄写的时候弄错了。

标签: mysql


【解决方案1】:

如果我理解正确,对于给定的gameid,您想返回spawns 表中的positions,而warriors 表中没有对应的positions?如果是这样,这是一个使用outer join / null 检查的选项。

select s.position
from spawns s
    join games g on g.map = s.map
    left join warriors w on w.game = g.id_game and s.position = w.position
where g.id_game = 1 and w.id_join is null

顺便说一句,另一种常见的方法是使用not exists。虽然大多数数据库都可以优化这种方法,但mysql 似乎遇到了麻烦。这里有一些关于这个问题的好帖子:

【讨论】:

  • 太棒了!我注意到你删除了not in() 函数,它看起来很干净。
【解决方案2】:

您可以使用NOT EXISTS 来从特定游戏中已在战士中使用的生成中排除位置:

SELECT s.position
FROM spawns AS s
INNER JOIN games AS g ON g.map = s.map
WHERE g.id_game = ? AND 
      NOT EXISTS (SELECT 1
                  FROM warriors AS w
                  WHERE w.game = g.id_game AND w.position = s.position)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多