棘手的 SQL 连接查询
Posted
技术标签:
【中文标题】棘手的 SQL 连接查询【英文标题】:Tricky SQL Join Query 【发布时间】:2012-12-07 07:24:38 【问题描述】:我有两张表,一张名为 StudentCerts,包含电子邮件(主键)和证书,另一张名为 CertReqs,包含证书和课程。表格的一部分可能如下所示:
StudentCerts: CertReqs:
Email Certificate Certificate Course
This@that.com Programmer Programmer CS 101
This@that.com English Programmer CS 202
A@B.com Econ Programmer CS 303
john@smith.com Programmer English ENG 101
English ENG 102
Econ ECON 102
Econ ECON 304
Art Art 101
Art Art 102
Journalism J 101
Journalism J 202
我想要做的是获得特定学生不属于的所有证书。例如,This@that.com 注册了程序员和英语证书,我想获得一条 SQL 语句,该语句将返回 CertReqs 中特定学生未注册的所有证书。所以对于这个例子它应该返回 Econ、Art 和 Journalism。 我一直在努力得到这个,所以任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:SELECT cr.Certificate FROM CertReqs cr
WHERE cr.Certificate NOT IN (
SELECT sc.Certificate FROM StudentCerts sc
WHERE sc.Email = 'This@that.com'
);
查询几乎读作要求:“我想要所有 CertReqs,学生不在其中”。
【讨论】:
非常感谢!这正是我想做的!【参考方案2】:游戏有点晚了,但一个简单的LEFT JOIN
很好地解决了这个问题:
SELECT DISTINCT cr.Certificate
FROM CertReqs cr
LEFT JOIN StudentCerts sc ON cr.Certificate = sc.Certificate AND sc.Email = 'This@that.com'
WHERE sc.Email IS NULL
【讨论】:
【参考方案3】:这将列出所有缺少某个证书的学生
SELECT DISTINCT x.*
FROM
(
SELECT a.Email, b.Certificate
FROM (SELECT DISTINCT Email FROM StudentCerts) a
CROSS JOIN
(SELECT DISTINCT Certificate FROM CertReqs) b
) x LEFT JOIN studentCerts y
ON x.Email = y.Email AND
x.Certificate = y.Certificate
WHERE y.Email IS NULL
ORDER BY x.EMAIL
SQLFiddle Demo
如果你想要特定的电子邮件,那么你只需要添加额外的条件
SELECT DISTINCT x.*
FROM
(
SELECT a.Email, b.Certificate
FROM (SELECT DISTINCT Email FROM StudentCerts) a
CROSS JOIN
(SELECT DISTINCT Certificate FROM CertReqs) b
) x LEFT JOIN studentCerts y
ON x.Email = y.Email AND
x.Certificate = y.Certificate
WHERE y.Email IS NULL AND
x.Email = 'This@that.com'
ORDER BY x.EMAIL
SQLFiddle Demo
【讨论】:
【参考方案4】:SELECT DISTINCT A.* fROM
(
SELECT DISTINCT EMAIL, CERTIFICATE fROM #StudentCerts A
CROSS JOIN #CertReqs B) A
LEFT JOIN #StudentCerts B ON A.EmaiL = B.EMAIL AND B.CERTIFICATES = A.Certificate
WHERE B.EMAIL IS NULL
ORDER BY A.EMAIL
【讨论】:
欢迎来到 Stack Overflow!虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!【参考方案5】:SELECT Certificate FROM `CertReqs`
WHERE Certificate NOT in(
SELECT Certificate
FROM `StudentCerts`
WHERE Email = 'This@that.com'
)
【讨论】:
以上是关于棘手的 SQL 连接查询的主要内容,如果未能解决你的问题,请参考以下文章