CodeGym /행동 /SQL SELF /SELECT 안에서 SELECT 사용하기

SELECT 안에서 SELECT 사용하기

SQL SELF
레벨 13, 레슨 1
사용 가능

상상해봐, 네가 대학에서 데이터 분석가로 일하고 있다고 쳐(우리 대학 데이터베이스 만들고 있잖아, 기억나지?). 그냥 학생들이랑 그들의 점수만 뽑는 게 아니라, 그룹에서 최고 점수도 같이 보여주는 컬럼을 추가해달라고 부탁받았어. 이렇게 하면 각 학생의 점수가 그룹 최고 점수랑 얼마나 차이 나는지 쉽게 볼 수 있지. 이걸 어떻게 해결할까? 당연히 SELECT 안에 서브쿼리 쓰는 거지!

SELECT 안의 서브쿼리는 메인 쿼리 실행할 때 바로 값을 계산할 수 있게 해줘. 이거 진짜 쩌는 게, 집계 계산, 복잡한 필터, 심지어 다른 데이터 모음까지 한 쿼리에서 조합할 수 있거든.

SELECT에서 서브쿼리 기본

SELECT 안의 서브쿼리는 말 그대로야: 한 SELECT 결과를 다른 SELECT 안에 넣는 거지. 이렇게 하면 결과의 각 행마다 추가 값을 계산할 수 있어.

간단한 예시로 가보자. 예를 들어, students 테이블이 이렇게 있다고 해보자:

student_id name group_id
1 Linda 101
2 Otto 102
3 Anna 101

그리고 grades 테이블:

grade_id student_id grade
1 1 5
2 1 4
3 2 3
4 3 5
5 3 4

예시 1: 그룹에서 최고 점수 추가하기

문제: 학생 이름, 점수, 그리고 그 학생이 속한 그룹의 최고 점수를 같이 보여줘서, 각 학생 점수가 그룹 최고 점수랑 얼마나 차이 나는지 볼 수 있게 해보자.

SQL 코드:

SELECT
    s.name AS student_name,
    g.grade AS student_grade,
    (
        SELECT MAX(grade) -- 이 쿼리는 딱 하나의 값만 반환해
        FROM grades 
        INNER JOIN students ON grades.student_id = students.student_id
        WHERE students.group_id = s.group_id
    ) AS max_group_grade 
FROM 
    students s
INNER JOIN 
    grades g ON s.student_id = g.student_id;

여기서 무슨 일이 일어나냐면:

  1. 각 학생마다 이름이랑 점수(s.name, g.grade)를 가져와.
  2. SELECT MAX(grade) — 이게 서브쿼리인데, 학생이 속한 그룹에서 최고 점수를 반환해.
  3. 서브쿼리는 메인 쿼리의 각 행마다 실행되고, WHERE students.group_id = s.group_id 조건으로 그룹을 한정해.

예시 2: 그룹별 평균 점수

분석가들한테 더 도움 주고 싶어? 최고 점수뿐만 아니라 그룹별 평균 점수도 같이 보여주자.

SQL 코드:

SELECT
    s.name AS student_name,
    g.grade AS student_grade,
    (
        SELECT AVG(grade) 
        FROM grades 
        INNER JOIN students ON grades.student_id = students.student_id
        WHERE students.group_id = s.group_id
    ) AS avg_group_grade
FROM 
    students s
INNER JOIN 
    grades g ON s.student_id = g.student_id;

이제:

  • MAX() 대신 AVG()를 써서 그룹 평균 점수를 계산해.
  • 실시간 데이터 분석이 가능해졌지.

제약사항과 팁

SELECT 안의 서브쿼리는 강력하지만, 쓸 때 주의할 점이 있어:

  1. 성능. 서브쿼리는 메인 쿼리의 각 행마다 실행돼. 테이블이 크면 SQL 쿼리 실행이 느려질 수 있어. 예를 들어, 학생이 1000명 있으면 서브쿼리도 1000번 실행되는 거야!
  2. 인덱스. 서브쿼리의 WHERE 조건에 쓰이는 컬럼에 인덱스를 잘 걸어두면 쿼리 속도가 빨라져.
  3. 가독성. 너무 복잡하게 중첩하지 말고, 서브쿼리가 너무 복잡해지면 FROM으로 빼거나 임시 테이블을 만들어서 써봐.

활용 예시

다른 재밌는 케이스도 몇 개 더 볼까?

예시 3: 각 학생의 수강 과목 수

각 학생이 몇 개의 과목을 듣고 있는지 보여주는 테이블을 만들어보자. enrollments 테이블이 student_id로 학생이랑 연결돼 있어:

student_id course_id
1 201
1 202
2 201
3 203

SQL 코드:

SELECT
    s.name AS student_name,
    (
        SELECT COUNT(*) 
        FROM enrollments
        WHERE enrollments.student_id = s.student_id
    ) AS course_count
FROM 
    students s;

여기서 서브쿼리는 각 학생에 대해 enrollments 테이블에서 몇 개의 레코드가 있는지 세는 거야.

예시 4: 각 학생의 "우등생" 플래그

학생이 우등생인지 아닌지 보여주자. 우등생 기준은 모든 점수가 5인 경우로 하자.

SQL 코드:

SELECT
    s.name AS student_name,
    (
        SELECT CASE 
            WHEN MIN(g.grade) = 5 THEN '우등생'
            ELSE '우등생 아님'
        END
        FROM grades g
        WHERE g.student_id = s.student_id
    ) AS status
FROM 
    students s;

여기서는 CASE를 중첩해서, 모든 점수가 5인 학생만 "우등생"으로 표시해.

SELECT 안의 서브쿼리 최적화

아까 성능 얘기했었지. 성능을 높이려면 이런 팁을 참고해봐:

  1. 인덱스 활용. 서브쿼리에서 데이터를 필터링한다면, 해당 컬럼에 인덱스가 있는지 꼭 확인해.
  2. 결과 캐싱. 때로는 서브쿼리를 VIEW나 임시 테이블로 빼는 게 더 나을 때도 있어.
  3. 중첩 줄이기. 너무 중첩해서 복잡하게 만들지 말고, 더 간단한 방법이 있으면 그걸 써.

SELECT 안의 서브쿼리는 계산이랑 데이터 분석에 엄청 많은 가능성을 열어줘. 물론 리소스를 많이 쓸 수도 있지만, 잘 최적화해서 쓰면 SQL이 훨씬 더 표현력 있고 유연해져. 그러니까 겁내지 말고 이것저것 실험해보면서 너만의 쿼리 최적화 방법을 찾아봐!

2
과제
SQL SELF, 레벨 13, 레슨 1
잠금
각 학생별 수강 과목 수 세기
각 학생별 수강 과목 수 세기
2
과제
SQL SELF, 레벨 13, 레슨 1
잠금
학생의 평균 점수 출력하기
학생의 평균 점수 출력하기
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION