Mysql 仅检索联接具有依赖性的行

Mysql 仅检索联接具有依赖性的行,mysql,sql,subquery,Mysql,Sql,Subquery,我正在创建一个测试系统,允许用户重新测试,直到通过测试。我想得到一个列表,对于给定的用户ID,分配给他们的测试的列表,在这个例子中,他们的分数低于100% 我有以下表格: 这里的一切都是为了简单而修改的,但它仍然应该是有效的 下面的查询可以帮助我找出分配给用户的所有测试,但我想从列表中删除这些测试 SELECT DISTINCT TestID, TestName FROM `Users` AS u RIGHT JOIN `Users_have_Tests` AS

我正在创建一个测试系统,允许用户重新测试,直到通过测试。我想得到一个列表,对于给定的用户ID,分配给他们的测试的列表,在这个例子中,他们的分数低于100%

我有以下表格:

这里的一切都是为了简单而修改的,但它仍然应该是有效的

下面的查询可以帮助我找出分配给用户的所有测试,但我想从列表中删除这些测试

SELECT DISTINCT
    TestID,
    TestName
FROM
    `Users` AS u
RIGHT JOIN
    `Users_have_Tests` AS ut
    ON
        u.UserID = ut.UserID
LEFT JOIN
    `Tests` AS t
    ON
        ut.TestID = t.TestID
WHERE UserID = 1
我觉得这里需要一个子查询。我提出了以下查询,以查找用户参加的每个测试的最高分数,但我不太确定如何将它们联系在一起。子查询对我来说是非常新的,我仍在努力理解它们

SELECT DISTINCT
    TestID,
    MAX(Percentage)
FROM
    `TestResults`
WHERE UserID = 1
GROUP BY TestID
我期待的结果是:

UserID = 1
+--------+----------+
| TestID | TestName |
+--------+----------+
|      3 |   Test 3 |
+--------+----------+

UserID = 2
+--------+----------+
| TestID | TestName |
+--------+----------+
|      2 |   Test 2 |
|      3 |   Test 3 |
+--------+----------+
我已经尝试了几种连接方式和条件,但是我不能完全理解我到底需要什么。谷歌和StackOverflow让我失望;可能是因为我不知道该找什么

编辑 以下是对我有效的方法:

SELECT DISTINCT t.TestID, t.TestName
    FROM 'Users' AS u
    RIGHT JOIN 'Users_have_Tests' AS ut
        ON u.UserID = ut.UserID
    LEFT JOIN 'Tests' AS t
        ON ut.TestID = t.TestID
    WHERE t.TestID NOT IN (
        SELECT tr.TestID
            FROM TestResults AS tr
            WHERE tr.Percentage >= 100
            AND tr.UserID = 2
        )
    AND u.UserID = 2

我可能遗漏了一些东西,但是为什么不运行下面的查询并处理结果呢

    SELECT ut.UserId, ut.TestId, t.TestName
    FROM `Users_Have_Tests` ut INNER JOIN `TestResults` r ON ut.TestId = r.TestId
      INNER JOIN `Tests` t ON t.TestId = r.TestId
    WHERE r.Percentage < 100
    ORDER BY ut.UserId, ut.TestId;

如果您计划对单个用户执行此操作,只需添加WHERE子句条目以根据单个用户ID值进行筛选。

您是否尝试过以下操作

编辑我注意到您希望看到最高分数,所以我创建了一个子查询

编辑我忘了分组

此外,Test需要在TestID和UserID上加入

        SELECT
            TestID,
            TestName,
            HighestScore
        FROM
            `Users` AS u
        RIGHT JOIN
            `Users_have_Tests` AS ut
            ON
                u.UserID = ut.UserID
        LEFT JOIN
        (   SELECT TestID, UserID, MAX(Percentage) AS HighestScore
            FROM `Tests`
            GROUP BY TestID, UserID         
        )AS t
            ON
                ut.TestID = t.TestID
            AND ut.UserID = t.UserID
        WHERE HighestScore < 100
        GROUP BY TestID, TestName, HighestScore

在having子句中尝试

打完电话

最大百分比为最高分数

在小组结束后说

最高的_分数<100

然后用最低及格分数替换100分。。只有没有超过通过的最大条目的测试才会被返回


我想我现在明白你的意思了,试试看:

SELECT DISTINCT
        TestID,
        TestName
    FROM
        `Users` AS u
    RIGHT JOIN
        `Users_have_Tests` AS ut
        ON
            u.UserID = ut.UserID
    LEFT JOIN
        `Tests` AS t
        ON
            ut.TestID = t.TestID
    WHERE TestID NOT IN (SELECT TestID
                         FROM TestResults
                         Where Percentage = 100)
    GROUP BY UserID

为什么不使用WHERE-Percentage 100呢?那么,你也可以使用GROUP-BYUserID@Calum使用WHERE百分比<100不起作用,因为如果用户在通过测试之前尝试了几次,这仍然等同于TRUE。按UserID分组将只返回一行,因为我已经有了WHERE UserID=$uidthink。我明白你的意思,我在下面发布了一个答案,如果您确实只需要一个特定的用户结果,那么只需删除GROUP BY语句,并使用and将您的UserID=1语句添加到WHERE子句中。如果没有其他解决方案,这可能会起作用,尽管这需要在后端进行大量编码。我必须创建一个测试数组,并对每个SQL行进行循环,以查看是否需要将其添加到数组中。不是最优雅的解决方案,当然也不是最快的。如果我只是想处理结果,我宁愿返回用户每次测试的最高分数,并根据该分数在我的程序中进行筛选。也许我不明白你在追求什么。。。您想要一个不同的用户列表吗?上面您声明您想要一个所有未通过测试的列表。这可能会导致每个用户有多行。此外,您还需要一个用户在任何测试中的最高分数或每个测试的最高分数?很抱歉造成混淆-我正在查找分配给特定用户的所有测试的列表,该用户尚未通过。因此,我可以向测试用户提供一个列表,他们仍然必须完成最大分数查询。我已返回每个测试的最大分数。啊哈!非常有用!我不得不稍微调整一下,但你让我走上了正确的道路!谢谢这里是我使用的:选择不同的t.TestID,t.TestName从'Users'作为u右键连接'Users\u have_Tests'作为u.UserID=ut.UserID左键连接'Tests'作为t在ut.TestID=t.TestID中,其中t.TestID不在,从TestResults中选择tr.TestID作为tr WHEREtr.百分比>=100,tr.UserID=2,u.UserID=2
SELECT DISTINCT
        TestID,
        TestName
    FROM
        `Users` AS u
    RIGHT JOIN
        `Users_have_Tests` AS ut
        ON
            u.UserID = ut.UserID
    LEFT JOIN
        `Tests` AS t
        ON
            ut.TestID = t.TestID
    WHERE TestID NOT IN (SELECT TestID
                         FROM TestResults
                         Where Percentage = 100)
    GROUP BY UserID