【问题标题】:Tricky SQL Join Query棘手的 SQL 连接查询
【发布时间】: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。 我一直在努力得到这个,所以任何帮助将不胜感激!

【问题讨论】:

    标签: mysql sql join


    【解决方案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
      

      如果你想要特定的电子邮件,那么你只需要添加额外的条件

      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
      

      【讨论】:

        【解决方案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' 
        )
        

        【讨论】:

          猜你喜欢
          • 2016-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-13
          • 2013-08-01
          • 1970-01-01
          • 2011-10-03
          • 2016-09-04
          相关资源
          最近更新 更多