我有一个包含3个常规表和2个链接表的模式,如下所示:
tutorial
id
exam
id
user
id
exam_user
user
exam
tutorial_user
user
tutorial
链接表确定哪些用户参加了哪个考试/教程。 从考试ID开始,我试图找到其成员参加考试的教程。
例如:
exam_user
+----+-------+----------+
| id | exam | user |
+----+-------+----------+
| 23 | 8 | 1 |
| 24 | 8 | 5 |
| 25 | 8 | 8 |
| 26 | 8 | 11 |
| 27 | 8 | 12 |
+----+-------+----------+
tutorial_user
+----+----------+----------+
| id | tutorial | user |
+----+----------+-----------
| 56 | 2 | 1 |
| 57 | 2 | 5 |
| 58 | 2 | 8 |
| 59 | 2 | 11 |
+----+----------+----------+
+----+----------+----------+
| id | tutorial | user |
+----+----------+-----------
| 60 | 3 | 1 |
| 61 | 3 | 5 |
| 62 | 3 | 8 |
| 63 | 3 | 15 |
+----+----------+----------+
教程2会匹配,因为所有条目都在考试8中,但教程3不会,因为用户11不在。
有没有(相对)有效的方法来实现上述目标?
答案 0 :(得分:0)
你怎么样尝试这样的事情:
select * from tutorial_user where tutorial not in
(
select tutorial from
(
(
select ex.exam, ex.user as ex_user, tut.tutorial as tutorial,
tut.user as tut_user from exam_user ex
inner join tutorial_user tut on
ex.User = tut.User
)
union all
(
select null, null, tutorial, user as tut_user from tutorial_user
)
) src
group by tutorial, tut_user
having count(tut_user) = 1
)
现在第一个查询应该给你一个看起来像这样的列表(基本上是每个用户的考试和教程的组合):
+----+-------+----------+-------------+---------+
| id | exam | user | Tutorial | User |
+----+-------+----------+-------------+---------+
| 23 | 8 | 1 | 2 | 1 |
| 23 | 8 | 1 | 3 | 1 |
| 24 | 8 | 5 | 2 | 5 |
| 24 | 8 | 5 | 3 | 5 |
...
接下来,通过对下一个查询进行联合,你最终会得到这样的结果:
+-----+-------+----------+-------------+---------+
| id | exam | user | Tutorial | User |
+-----+-------+----------+-------------+---------+
| 23 | 8 | 1 | 2 | 1 |
| 23 | 8 | 1 | 3 | 1 |
| 24 | 8 | 5 | 2 | 5 |
| 24 | 8 | 5 | 3 | 5 |
| null| null | null | 2 | 1 |
| null| null | null | 2 | 5 |
| null| null | null | 2 | 8 |
...
基本上,这使我们能够做的是一个分组声明,它将突出显示教程表中的用户,而不是检查表中的用户。所述重点将与having()子句一起使用。如果计数为1,那么教程表中的某个人不在考试表中。你现在要做的就是从教程表中选择不属于你所发现的教程的教程,你应该做得很好。