Sql 仅当子表中的多行匹配时才从父表中选择行

Sql 仅当子表中的多行匹配时才从父表中选择行,sql,ms-access,Sql,Ms Access,我正在构建一个代码,通过在数据库中保存信息来学习tic-tac-toe。 我有两张桌子,Games(ID,Winner)和Turns(ID,Turn,GameID,Place,Shape)。 我想通过多个子信息找到父项。 例如: SELECT GameID FROM Turns WHERE GameID IN (WHEN Turn = 1 THEN Place = 1) AND GameID IN (WHEN Turn = 2 THEN Place = 4); 这样的事情可能吗? 我正在使用m

我正在构建一个代码,通过在数据库中保存信息来学习tic-tac-toe。 我有两张桌子,
Games(ID,Winner)
Turns(ID,Turn,GameID,Place,Shape)
。 我想通过多个子信息找到父项。
例如:

SELECT GameID FROM Turns WHERE
GameID IN (WHEN Turn = 1 THEN Place = 1) AND GameID IN (WHEN Turn = 2 THEN Place = 4);
这样的事情可能吗?
我正在使用ms access。

Turm-游戏回合
游戏ID-游戏ID
地点-矩阵上的地点 1=右上角,9=左下角
形状-X或圆形

提前谢谢

select GameID from Games g where exists (select * from turns t where 
t.gameid = g.gameId and ((turn =1 and place = 1) or (turn =2 and place =5)))
这将选择所有至少有一个回合且符合相应标准的游戏

有关exist的更多信息:

我绕过了这个问题,添加了一个列作为字符串示例保存转折点:“154728”,然后我搜索它。我认为此解决方案对数据库的要求也较低

您的问题的一般解决方案可以通过使用子查询来实现,该子查询包含两个表实例之间的自联接:

SELECT * FROM Games
WHERE GameID IN 
(
    SELECT Turns1.GameID
    FROM Turns AS Turns1 
    INNER JOIN Turns AS Turns2 
    ON Turns1.GameID = Turns2.GameID
    WHERE (
        (Turns1.Turn=1 AND Turns1.Place = 1) 
        AND 
        (Turns2.Turn=2 AND Turns2.Place = 4))
);
转弯(别名转弯1和转弯2)之间的自连接是关键,因为如果您尝试同时应用两组条件,如下所示:

WHERE (
        (Turns.Turn=1 AND Turns.Place = 1) 
        AND 
        (Turns.Turn=2 AND Turns.Place = 4))
你再也回不来了。这是因为在您的表中,单个行无法同时满足这两个条件


我使用Access的经验是,要执行类似这样的复杂查询,必须使用SQL视图并自己键入查询,而不是使用查询设计器。在设计器中可能会这样做,但对我来说,自己编写代码总是容易得多。

这个非常简单的查询将在一次扫描中完成,并且不需要通过在字符串中存储多个值来违反第一范式(抖动)

正如其他答案所建议的那样,没有必要加入以确定此信息


请在数据库中使用正确的数据库设计原则,不要将多个值存储在一个字符串中,从而违反第一个标准格式

我不确定我是否理解你的逻辑。。请解释你想要达到的目标。我想要选择一款游戏,它有一个有信息的孩子(回合=1,地点=1),也有一个有信息的孩子(回合=2,地点=5)。通过向表中添加另一列,我绕过了这个问题,但我仍然想知道如果我再次需要它,是否有解决方案。谢谢你的回答,但我需要两个条件来应用,而不仅仅是一个。如果子查询中没有自联接,这将无法工作,甚至将“or”改为“and”,因为没有行同时满足这两个条件。@Gary.Ray您声称
存在
优于
中的
,这是基于10年前的误解。“大多数(如果不是所有的话)RDBMS…为每一行重新执行…这显然是错误的。”我认为这不是一个好的长期解决方案,因为它违反了第一个标准形式。我完全同意。我认为有这样一个适当的限制。
SELECT T.GameID
FROM Turns AS T
WHERE
   (T.Turn = 1 AND T.Place = 1)
   OR (T.Turn = 2 AND T.Place = 4)
GROUP BY T.GameID
HAVING Count(*) = 2;