2011-11-03 6 views
3

Oracle 10g를 사용하여 SQL을 배우고 있습니다. 업데이트 문장에서 가장 많은 직원이 근무하는 부서를 반환하는 쿼리가 필요합니다. 나는 이미 그것을 해결,하지만 난이 쿼리가 작동하지 않습니다 이유를 알아낼 수 :"ANY"가 제대로 작동하지 않는 이유는 무엇입니까?

select deptno 
    from (select deptno, 
       count(*) num 
      from emp 
     group by deptno) 
where not exists(select deptno, 
          count(*) 
        from emp 
        having count(*) > num 
        group by deptno) 
: 그것은 더는 다음에 해당하는 최적화되어야 설명서에 따라 이후 나 퍼즐

select deptno 
from (select deptno, 
      count(*) num 
     from emp 
     group by deptno) 
where not num < any(select count(deptno) 
         from emp 
        group by deptno) 

오류없이 작동합니다. 다음은 또한 작동합니다 :

select deptno 
    from (select deptno, 
       count(*) num 
      from emp 
     group by deptno) 
where num = (select max(alias) 
       from (select count(deptno) alias 
         from emp 
         group by deptno)) 


select deptno 
    from emp 
group by deptno 
having not count(deptno) < any(select count(deptno) 
            from emp 
            group by deptno) 

편집. 아마 inner select의 반환 값을 게시하면 도움이 될 것입니다.

첫 번째 선택 반환 :

Dept. Number   Employees 
30     6 
20     5 
10     3 

마지막 하나가 반환 (3,5,6)

나는 개별적으로 확인. 또한 값을 수동으로 입력하면 예상대로 작동하며 대부분의 직원이있는 부서로 30을 반환합니다.

select deptno 
from (select deptno, 
      count(*) num 
     from emp 
     group by deptno) 
where not num < any(6,5,3) 

아마, 오라클 10g에게 10.2.0.1.0

마지막 편집을 사용하고 있습니다. 어떤 일이 일어나고 있는지 아직 알 수는 없지만, 마지막 선택이 어떻게 든 null을 반환하는 것처럼 동작합니다. 따라서 '제거'하지 않아도 여전히 아무것도 선택하지 않습니다.

누군가가 관심이있는 경우에도 다음과 같이 유용하다는 것을 발견했습니다. TSQL - SOME | ANY why are they same with different names? 첫 번째 대답을 읽어보십시오. 모든/some, all을 사용하지 않는 것이 좋습니다.

답변

1

보정 (갱신)

not num < any(select ...) 

는 다른 쿼리와 동일해야합니다. 다음 유사 콘텐츠를 사용해보세요.

num >= ALL(select ...) 

하지만 내가 잘못된 결과를주는 이유를 이해할 수 없습니다. 아마도 not 우선 순위 때문일 것입니다. 수 대신 trythis?

not (num < ANY(select ...)) 

전체 쿼리 :

select deptno 
from (select deptno, count(*) num from emp group by deptno) 
where num >= all(select count(deptno) from emp group by deptno) 

과 :

select deptno 
from (select deptno, count(*) num from emp group by deptno) 
where not (num < any(select count(deptno) from emp group by deptno)) 
+1

나는 num> onedaywhen

+0

나는 마지막 부분을 얻었는지 확실하지 않지만 더 명확하게 편집한다. 또한 _some_과 _any_는 같은 연산자로 간주되고 num> = any (select ...)는 모든 행이 적어도 자신과 동일하기 때문에 모든 행을 반환합니다. 'num> = any (select ...)'는 5,6이 모두 3보다 커지기 때문에 true입니다. –

+0

네, 맞습니다. 나는'ALL'을 생각하고'ANY'를 쓰고 있었다. –

2

여기 (표준 SQL을 일을 명확히 할 수 비슷한 예입니다, 쉽게 할 수있다 오라클을 위해 변형 됨) :

WITH T 
    AS 
    (
     SELECT * 
     FROM (
       VALUES (0), 
        (1), 
        (2), 
        (NULL) 
      ) AS T (c) 
    ) 
SELECT DISTINCT c 
    FROM T 
WHERE 1 > ALL (SELECT c FROM T T2); 

이것은 빈 집합을 반환합니다. 이는 테이블에 null이 있으면 NULL이 지정되어 있으므로 UNKNOWN이므로 값 1이 집합의 모든 값보다 큰지 여부를 알 수 없습니다.

그러나 NOT 연산자 추가 : 널 값을 포함하는 세트

WHERE NOT 1 > ALL (SELECT c FROM T T2); 

모든 값을 반환. 언뜻보기에 이것은 틀린 것처럼 보입니다. 1 > 2이 거짓이라는 것을 감안할 때 값 1이 null에 관계없이 세트의 모든 값보다 크지 않다는 것을 확실하게 말할 수 있습니다.

그러나이 경우 NOT은 이전 결과를 단순히 뒤집을뿐입니다. 즉 모든 행이 반대 인 경우는 모든 행입니다.)

는 또한 열 (1보다는 리터럴 값)을 비교하여 부정을 고려

WHERE NOT c > ALL (SELECT c FROM T T2); 

가 널값을 제외한 모든 행을 반환 이번에.

+0

이봐, 정말로 알고있는 것이 좋다. 결코 내 마음을 넘어서지 못했다. 그러나 null 값이 없습니다. (나는 이것을 명확히하기 위해 편집했다.) 내가 수동으로 바꾸면 값을 반환하는 값을 마지막으로 선택하면된다. 작동하지 않을 것이고, 'NOT'을 생략하고 연산자'>'또는'<'를 바꾸는 것보다 훨씬 더 이상하다. 결과는 같을 것이다. 선택한 행이 없습니다. (SQL은 아마 나를 싫어한다.) –

+0

드디어 그 마지막 것을 얻은 것 같아. 최초의 표현이 null의 경우, all의 결과는 true 또는 false가 아니고, 값이면 all과 비교할 수없고 false를 반환합니다. 이렇게하면'num'은 null로 취급되지만, 두 번째 select 및 not values ​​만 사용하는 경우에만 가능합니다. : S (또 다른 이상한 상황에 감사드립니다!) –

관련 문제