Post

SQL - SUBQUERY

Subquery

쿼리로 걸러낸 데이터를 추가로 쿼리를 통해 걸러내는 중첩 쿼리문이라고 할 수 있다.

해당 subquery에 대해 설명할 때 아래의 table을 사용하여 설명하도록 하겠다.

img.png

  • 두 개의 쿼리
    1
    2
    3
    
    SELECT college_id
    FROM college
    WHRE name = 'Engineering' or name = 'Nursing';
    

    img_1.png

    위 쿼리의 결과인 1,2를 아래의 쿼리로 처리하는 것

    1
    2
    3
    
    SELECT user
    FROM student
    WHERE cid in (1,2);
    

    img_2.png

  • Subquery로 하나로 합친 쿼리
    1
    2
    3
    4
    5
    6
    7
    
    SELECT user
    FROM student
    WHERE cid in 
    (SELECT college_id
    FROM college
    WHERE name = 'Engineering' or name = 'Nursing');
    -- 연산 결과가 한 개 일 경우 in 대신 =로 대체 가능
    

    img_3.png

자주 사용하는 연산자

  • any
    다중 행 연산자로 조건을 만족하는 값이 하나라도 있다면 반환한다.

    1
    2
    3
    4
    5
    
    SELECT *
    FROM student
    WHERE GRADE > ANY(SELECT GRADE FROM STUDENT WHERE cid = 3);
    -- cid 값이 1인 뭐든 한 개 이상의 레코드의 grade 보다 더 높은 grade를 가진 레코드를 출력
    -- 즉 최소 grade를 가진 레코드보다 더 높은 grade를 가진 레코드만 출력
    

    전체 학생 중 cid가 2인 학생중에 가장 낮은 점수는 2.8, 이 이상 높은 grade를 사진 학생들을 모두 출력

    img_4.png

  • all 다중 행 연산자로 모든 조건을 만족하는 값을 반환한다.

    1
    2
    3
    4
    5
    
    SELECT *
    FROM student
    WHERE GRADE > ALL(SELECT GRADE FROM STUDENT WHERE cid = 2);
    -- cid 값이 2인 모든 레코드의 grade 보다 더 높은 grade를 가진 레코드만 출력
    -- 즉 cid가 2인 레코드들 중 최대 grade를 가진 레코드보다 더 높은 grade를 가진 레코드만 출력
    

    img_5.png

  • exists subquery의 결과 값이 한 개 이상 존재할 경우 true를 반환한다.

    1
    2
    3
    4
    5
    6
    
    SELECT * 
    FROM circle c
    WHERE exists (select sid
    from student
    where circle = c.circle_id)
    -- student에 circle 값에 있는 circle table 값만 전체 갖고 와서 출력
    

    img_6.png

그 외

  • 중첩 subquery subquery 안에 subquery가 존재할 수 있다.
    1
    2
    3
    4
    5
    6
    7
    8
    
    SELECT * 
    FROM student
    WHERE grade =
    (select max(grade) from student where cid in
    (select college_id from college
    where name = 'Engineering'));
    -- college table의 college가 'Engineering'인 레코드의 college_id 값을 가져온 것 중에
    -- grade 값이 가장 높은 레코드 값을 출력
    

    img_7.png

  • subquery 다중 필드 비교 subquery는 여러 개의 필드를 대상으로 비교할 수 있다.
    1
    2
    3
    4
    5
    
    SELECT user, grade, cid 
    FROM student
    WHERE (grade, cid) in
    (select max(grade), cid from student group by cid);
    -- student table에서 grade값이 최고값인 레코드를 cid로 group화하여 name과 grade, cid를 출력
    

    img_8.png

  • HAVING 사용 subquery로 group by를 이용하고 having도 사용이 가능하다.
    1
    2
    3
    4
    5
    6
    7
    
    SELECT cid, avg(grade) 
    FROM student
    GROUP BY cid
    HAVING avg(grade) > (select avg(grade)
    from student
    where cid = 3);
    -- student table에서 deptno가 3인 레코드의 grade의 평균보다 더 높은 grade를 가진 레코드의 cid와 평균 grade를 출력
    

    img_9.png

참고자료

This post is licensed under CC BY 4.0 by the author.