仅检索关节具有依赖性的行
Retrieving only rows for which a join has a dependancy
我正在创建一个测试系统,允许用户重新测试直到通过。我想为给定的 UserID 获取分配给他们的测试列表,这些测试的分数低于通过(此示例为 100%)。
我有以下表格:
(Everything here has been adapted for simplicity, but it should all be valid still)
Users
(Generic "users" table with UserID and Name, etc...)
Tests
+--------+----------+------------------+
| TestID | TestName | OtherTestColumns |
+--------+----------+------------------+
| 1 | Test 1 | Blah.... |
| 2 | Test 2 | Blah.... |
| 3 | Test 3 | Blah.... |
| 4 | Test 4 | Blah.... |
+--------+----------+------------------+
Users_Have_Tests
Users are assigned tests they must take with this table
+--------+--------+
| UserID | TestID |
+--------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
+--------+--------+
TestResults
+--------+--------+------------+
| TestID | UserID | Percentage |
+--------+--------+------------+
| 1 | 1 | 75 |
| 1 | 1 | 100 |
| 2 | 1 | 80 |
| 2 | 1 | 100 |
| 1 | 2 | 100 |
| 2 | 2 | 75 |
+--------+--------+------------+
我可以使用以下查询找出分配给用户的所有测试,但我想从该列表中删除他们已通过的测试
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 |
+--------+----------+
我已经尝试了多种连接和条件方式,但我无法完全理解我在这里到底需要什么。 Google 和 Whosebug 让我失望了;可能是因为我不知道要搜索什么。
编辑
以下是对我有用的:
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 子句条目以针对单个 UserId 值进行过滤。
您尝试过以下方法吗?
编辑我注意到你想看到最高分,所以我创建了一个子查询
编辑我忘了分组。
此外,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 子句
调用后
MAX(百分比)AS HighestScore
分组后
拥有 Highest_Score < 100
然后将 100 替换为最低及格分数。只有没有超过及格分数的测试才会被返回。
http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
我想我明白你现在想要什么了,试试看吧:
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
我正在创建一个测试系统,允许用户重新测试直到通过。我想为给定的 UserID 获取分配给他们的测试列表,这些测试的分数低于通过(此示例为 100%)。
我有以下表格:
(Everything here has been adapted for simplicity, but it should all be valid still)
Users
(Generic "users" table with UserID and Name, etc...)
Tests
+--------+----------+------------------+
| TestID | TestName | OtherTestColumns |
+--------+----------+------------------+
| 1 | Test 1 | Blah.... |
| 2 | Test 2 | Blah.... |
| 3 | Test 3 | Blah.... |
| 4 | Test 4 | Blah.... |
+--------+----------+------------------+
Users_Have_Tests
Users are assigned tests they must take with this table
+--------+--------+
| UserID | TestID |
+--------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
+--------+--------+
TestResults
+--------+--------+------------+
| TestID | UserID | Percentage |
+--------+--------+------------+
| 1 | 1 | 75 |
| 1 | 1 | 100 |
| 2 | 1 | 80 |
| 2 | 1 | 100 |
| 1 | 2 | 100 |
| 2 | 2 | 75 |
+--------+--------+------------+
我可以使用以下查询找出分配给用户的所有测试,但我想从该列表中删除他们已通过的测试
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 |
+--------+----------+
我已经尝试了多种连接和条件方式,但我无法完全理解我在这里到底需要什么。 Google 和 Whosebug 让我失望了;可能是因为我不知道要搜索什么。
编辑 以下是对我有用的:
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 子句条目以针对单个 UserId 值进行过滤。
您尝试过以下方法吗?
编辑我注意到你想看到最高分,所以我创建了一个子查询
编辑我忘了分组。
此外,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 子句
调用后
MAX(百分比)AS HighestScore
分组后
拥有 Highest_Score < 100
然后将 100 替换为最低及格分数。只有没有超过及格分数的测试才会被返回。
http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
我想我明白你现在想要什么了,试试看吧:
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