【问题标题】:SQL: Select groups that do not contain a certain valueSQL:选择不包含特定值的组
【发布时间】:2018-04-28 16:47:21
【问题描述】:

我使用 Microsoft SQL Server Management Studio 2014,我有这 3 个表:

员工

EMPID | FIRSTNAME
  1   | JOHNNY
  2   | DWAYNE
  3   | TOM
  4   | CHRISTIAN
  5   | JACK
  6   | BRAD
  7   | ADAM
  8   | MATT
  9   | WILL
  10  | JIM

飞机

AID | NAME
 1  | BOEING 1
 2  | BOEING 2
 3  | BOEING 3
 4  | BOEING 4
 5  | AIRBUS 1
 6  | AIRBUS 2
 7  | LEARJET
 8  | DOUGLAS
 9  | JUMBO
 10 | ILYUSHIN

认证

EMPID | AID
  1   |  1
  1   |  2
  1   |  3
  1   |  4
  4   |  2
  4   |  3
  7   |  1
  7   |  2
  7   |  5
  7   |  6
  8   |  7
  8   |  8
  8   |  9
  2   |  10
  2   |  1
  2   |  9
  3   |  10
  5   |  8
  5   |  9

这个概念是有 10 名员工和 10 架飞机。 CERTIFIED 表确定了哪些员工有权驾驶哪些飞机。不过,并非所有员工都是飞行员。我需要以某种方式选择所有未获得使用波音认证的飞行员。我试过但没有奏效的方法如下:

SELECT DISTINCT FIRSTNAME
FROM EMPLOYEES
WHERE EMPID IN (SELECT EMPID
                FROM CERTIFIED
                WHERE AID NOT IN (SELECT AID FROM AIRCRAFTS WHERE NAME LIKE 'BOEING%'))

这给出了这些结果:

JACK
MATT
TOM
ADAM
DWAYNE

这是错误的,因为根据 CERTIFIED 表,ADAM 和 DWAYNE 被授权驾驶至少一架波音。

任何帮助将不胜感激,在此先感谢!

【问题讨论】:

    标签: sql sql-server database


    【解决方案1】:

    我认为您的问题是针对在非波音飞机上获得认证的任何员工——一组略有不同的人。

    对于你的问题,我会去not exists

    select e.*
    from employees e
    where not exists (select 1
                      from certified c join
                           aircrafts a
                           on c.aid = a.aid
                      where e.empid = c.empid and a.name like '%BOEING%'
                     );
    

    另一种方法——如果你只想要员工 ID——使用聚合和having

    select e.empid, e.firstname
    from employees e join
         certified c
         on e.empid = c.empid join
         aircrafts a
         on c.aid = a.aid
    group by e.empid, e.firstname
    having sum(case when a.name like '%BOEING%' then 1 else 0 end) = 0;
    

    我碰巧喜欢这种方法,因为它很容易推广到其他条件 - 例如飞行波音但不飞行空中客车或飞行 Learjet 和 Cessna。

    【讨论】:

    • 你的方法我都试过了。不幸的是,您的第一个没有任何回报。您的第二种方法效果很好,谢谢:)
    【解决方案2】:

    试试这个查询...

    SELECT employees.empid, Max(employees.firstname) AS FirstName 
    FROM   certified 
           INNER JOIN employees ON employees.empid = certified.empid 
    WHERE  certified.empid NOT IN (SELECT certified.empid 
                                   FROM   certified 
                                   INNER JOIN aircrafts ON aircrafts.aid = certified.aid 
                                   WHERE  aircrafts.NAME LIKE 'BOEING%') 
    GROUP  BY employees.empid 
    

    演示:http://www.sqlfiddle.com/#!18/8f26d/27/0

    结果

    +-------+-----------+
    | EMPID | FirstName |
    +-------+-----------+
    |     3 | TOM       |
    |     5 | JACK      |
    |     8 | MATT      |
    +-------+-----------+
    

    【讨论】:

    • 谢谢,这是完美的
    • 很高兴听到这个消息。
    【解决方案3】:

    您应该使用NOT IN 经波音认证的emp 与飞机连接

    SELECT DISTINCT FIRSTNAME
    FROM EMPLOYEES
    WHERE EMPID NOT IN (SELECT EMPID
                    FROM CERTIFIED c 
                    INNER JOIN AIRCRAFTS a ON on a.AID  = c.AID 
                    WHERE a.NAME LIKE 'BOEING%')
    

    【讨论】:

    • 这仍然返回错误的值:CHRISTIAN JIM JOHNNY WILL BRAD
    猜你喜欢
    • 2012-03-10
    • 2015-03-06
    • 1970-01-01
    • 2021-09-15
    • 2014-08-04
    • 2020-11-25
    • 2012-03-10
    • 1970-01-01
    • 2016-05-28
    相关资源
    最近更新 更多