我有一个查询要生产,我似乎无法做对。我有三张桌子:
student
:学生详情
link
:学生存在的链接,链接的状态可以是活动的或已完成
email
:显示通过电子邮件发送的链接。
我需要根据以下标准获取学生ID列表(来自学生表):
所以如果我的表中有以下数据:
student
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
+----+
link
+----+-----------+------------+
| id | status | student_id |
+----+-----------+------------+
| 1 | completed | 1 |
| 2 | active | 1 |
| 3 | completed | 2 |
| 4 | active | 3 |
+----+-----------+------------+
email
+----+---------+
| id | link_id |
+----+---------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+---------+
然后我的查询应返回以下学生ID:2,3,4
2 - 因为此学生只有一个完整的链接
3 - 因为存在没有关联电子邮件的活动链接
4 - 因为此学生没有链接
我目前有这个查询,它可以满足我的需求:
SELECT DISTINCT student.id
FROM student
LEFT JOIN link ON link.student_id = student.id
LEFT JOIN email ON email.link_id = link.id
WHERE student.course = 'phd'
AND student.institution_id = '2'
AND (
(link.status != "active" AND email.id IS NULL)
OR
(link.status IS NULL AND email.id IS NULL)
OR
(link.status = "active" AND email.id IS NULL)
)
这当然没有获得任何学生ID,其中link.status =已完成且学生没有其他链接。我当然可以通过添加:
来做到这一点(link.status = "completed" and email.id IS NOT NULL)
进入WHERE
,但如果他们有另一个活动链接或者他们没有活动链接,这将返回学生ID。这是我正在努力的一点。
我觉得这可能无法通过单个查询完成,所以我需要做两个查询然后相互减去它们吗?即上面的查询和单独的查询选择具有“已完成”状态的链接,然后从第一个查询中减去它们?
我使用这些查询的应用程序是用PHP构建的,所以我很乐意在PHP中使用两个查询做一些逻辑。如果需要的话。
(我不知道该怎么做标题所以如果有人能想到更好的东西请编辑它!)
答案 0 :(得分:2)
因为您的请求基于链接而且一个学生可以有多个链接,所以您应该从查询到链接表开始,然后添加联接和条件。
准备SQL:
CREATE TABLE IF NOT EXISTS student
(
id int auto_increment primary key,
course tinytext,
institution_id int
);
INSERT INTO student (id, course, institution_id) VALUES
(1, 'phd', 2),
(2, 'phd', 2),
(3, 'phd', 2),
(4, 'phd', 2);
CREATE TABLE IF NOT EXISTS link
(
id int auto_increment primary key,
status tinytext,
student_id int
);
INSERT INTO link (id, status, student_id) VALUES
(1, 'completed', 1),
(2, 'active', 1),
(3, 'completed', 2),
(4, 'active', 3);
CREATE TABLE IF NOT EXISTS email
(
id int auto_increment primary key,
link_id int
);
INSERT INTO email (id, link_id) VALUES
(1, 1),
(2, 2),
(3, 3);
查询:
SELECT DISTINCT s.id
FROM link l
LEFT JOIN student s ON l.student_id = s.id
LEFT JOIN email e ON l.id = e.link_id
WHERE s.course = 'phd'
AND s.institution_id = '2'
AND (
(l.status != "active" AND e.id IS NULL)
OR
(l.status IS NULL AND e.id IS NULL)
OR
(l.status = "active" AND e.id IS NULL)
)
玩它:http://sqlfiddle.com/#!2/dae16b/2
我真的不明白你的问题,因为你有很多错误。我会尝试深入挖掘,看看你的逻辑是否正常。
编辑:通过过滤JOIN的“草莓”方法可能是你需要的东西SELECT s.id
FROM student s
LEFT JOIN link l
ON l.student_id = s.id AND l.status = 'active' OR l.status IS NULL
LEFT JOIN email e
ON e.link_id = l.id
WHERE
e.id IS NULL
AND s.course = 'phd'
AND s.institution_id = '2';
玩它:http://sqlfiddle.com/#!2/dae16b/26
我们选择“学生”表并仅添加具有“活动”或“空”状态(LEFT JOIN link l ON l.student_id = s.id AND l.status != 'completed'
)的链接,这些链接解决了规则#2(该学生没有现有链接)和规则#1的第一部分(已创建链接但尚未通过电子邮件发送)和规则#3的第二部分(link.status =已完成,有此学生没有其他具有活动状态的链接)。之后,要解决第二条规则#2(已创建链接但尚未通过电子邮件发送),我们会删除没有电子邮件的行({ {1}}和JOIN email e ON e.link_id = l.id
部分)。
如果您需要解决规则#3的第一部分( link.status =已完成,并且该学生没有其他具有活动状态的链接),因为我不知道,如果“学生没有链接”=“学生有链接完成状态”的情况。
现在,此查询会返回您请求的内容。
答案 1 :(得分:2)
SELECT s.*
FROM student s
LEFT
JOIN link l
ON l.student_id = s.id
AND l.status <> 'completed'
LEFT
JOIN email e
ON e.link_id = l.id
WHERE e.id IS NULL;