在SQL QUERY不一致的WHERE子句中将AND IN与AND连接

时间:2014-11-26 14:42:07

标签: php mysql sql oracle

这是我的崩溃。如果我跑:

SELECT pnumber, count(distinct ssn) as  num_emps,nvl(sum(hours),0) as thours, nvl(sum(hours*salary/2000),0) as tcost 
   FROM project 
    LEFT JOIN (works_on join (employee 
    LEFT JOIN Department on DNO=DNUMBER) on essn=ssn) 
   ON pnumber=pno 
GROUP BY pnumber 
ORDER BY pnumber

我得到了

 PNUMBER   NUM_EMPS     THOURS      TCOST
---------- ---------- ---------- ----------
     1          4       67.5     1027.5
     2          3       37.5      562.5
     3          2         50        960
    10          3         55      762.5
    20          3         25      522.5
    30          4         60      967.5
    40          0          0          0
    50          0          0          0
    60          0          0          0

当我跑步时:

SELECT pnumber, count(distinct ssn) as  num_emps,nvl(sum(hours),0) as thours, nvl(sum(hours*salary/2000),0) as tcost 
   FROM project 
    LEFT JOIN (works_on join (employee 
        LEFT JOIN Department on DNO=DNUMBER) on essn=ssn) 
    ON pnumber=pno 
WHERE  ssn IN (select MGRSSN from DEPARTMENT)
GROUP BY pnumber 
ORDER BY pnumber

我得到了

 PNUMBER   NUM_EMPS     THOURS      TCOST
---------- ---------- ---------- ----------
     1          1          5        100
     2          1         10        200
     3          1         10        200
    10          1         10        200
    20          3         25      522.5
    30          2         25        530

到目前为止,让我们试试这个:

SELECT pnumber, count(distinct ssn) as  num_emps,nvl(sum(hours),0) as thours, nvl(sum(hours*salary/2000),0) as tcost 
   FROM project 
    LEFT JOIN (works_on join (employee 
        LEFT JOIN Department on DNO=DNUMBER) on essn=ssn) 
    ON pnumber=pno 
WHERE  ssn IN (select SUPERSSN from EMPLOYEE) AND ssn NOT IN (select MGRSSN from DEPARTMENT)
GROUP BY pnumber 
ORDER BY pnumber

我明白了:

 PNUMBER   NUM_EMPS     THOURS      TCOST
---------- ---------- ---------- ----------
     1          1       32.5      487.5
     2          1        7.5      112.5

也很好,但是当我尝试这个时(我所做的只是在Where子句中添加另一个Not):

SELECT pnumber, count(distinct ssn) as  num_emps,nvl(sum(hours),0) as thours, nvl(sum(hours*salary/2000),0) as tcost 
   FROM project 
   LEFT JOIN (works_on join (employee 
       LEFT JOIN Department on DNO=DNUMBER) on essn=ssn) 
   ON pnumber=pno 
WHERE  ssn NOT IN (select SUPERSSN from EMPLOYEE) AND ssn NOT IN (select MGRSSN from DEPARTMENT)
GROUP BY pnumber 
ORDER BY pnumber

我得到“没有选择行”!怎么样?还应该有2名员工不是第1号的经理或主管。请帮忙吗?谢谢,

修改

这是只有一个NOT IN的结果:

SQL> SELECT pnumber, count(distinct ssn) as  num_emps,nvl(sum(hours),0) as thours, nvl(sum(hours*salary/2000),0) as tcost
  2     FROM project
  3     LEFT JOIN (works_on join (employee
  4         LEFT JOIN Department on DNO=DNUMBER) on essn=ssn)
  5     ON pnumber=pno
  6  WHERE ssn NOT IN (select MGRSSN from DEPARTMENT)
  7  GROUP BY pnumber
  8  ORDER BY pnumber;

PNUMBER   NUM_EMPS     THOURS      TCOST
---------- ---------- ---------- ----------
     1          3       62.5      927.5
     2          2       27.5      362.5
     3          1         40        760
    10          2         45      562.5
    30          2         35      437.5

2 个答案:

答案 0 :(得分:1)

NOT IN不会返回任何值为NULL的行。所以:

WHERE ssn NOT IN (select SUPERSSN from EMPLOYEE)
如果SUPERSSN行为NULL,则

会过滤所有内容。以下是两种解决方法:

WHERE ssn NOT IN (select SUPERSSN from EMPLOYEE where SUPERSSN is not null)

或:

WHERE NOT EXISTS (select 1 from EMPLOYEE e where e.SUPERSSN = ssn)

(您可能需要ssn上的别名,但我不知道它来自哪个表。)换句话说,NOT EXISTSNOT IN的语义不同有一个NULL值。 NOT EXISTS(在我看来)具有更直观的行为。

现在,如果其中一个值是NULL

,为什么这永远不会返回true
WHERE ssn NOT IN (select SUPERSSN from EMPLOYEE)

如果ssn列在SUPERSSN中,则返回false。这很容易。如果ssn不在列表中,则没有值为NULL,则返回true。这很容易。

如果ssn位于列表中且其中一个SUPERSSN值为NULL,那么就会出现一个难题。 ssn是否等于NULL值。好吧,既不。与NULL的比较返回NULL。并且,NULLWHERE子句中被视为“不正确”。简而言之,如果SUPERSSN的值为NULL,则表达式只能返回false或NULL - 并且所有内容都会被过滤掉。

答案 1 :(得分:0)

尝试:

WHES ssn NOT IN(从EMPLOYEE联盟中选择SUPERSSN从部门选择MGRSSN)