코딩일기/자격증

[정보처리기사] SQL | JOIN + GROUP BY + 서브쿼리 문제 | 2024년 3회 정보처리기사 실기 기출문제

jhy_2023 2025. 5. 30. 17:23
728x90
반응형

2024년 3회 정보처리기사 실기 기출문제

문제

아래와 같은 테이블이 있을때, 다음 SQL 문의 결과는?

SELECT count(*)
FROM employee AS e JOIN project AS p ON e.project_id = p.project_id
WHERE p.name IN (
    SELECT name FROM project p WHERE p.project_id IN (
        SELECT project_id FROM employee GROUP BY project_id HAVING count(*) < 2
    )
);

정답

1

반응형

해설

📌 기본개념

1️⃣ JOIN

JOIN은 두 개 이상의 테이블을 연결할 때 사용합니다.
이 문제에서는 employee 테이블과 project 테이블을 project_id를 기준으로 내부 조인(INNER JOIN)하고 있습니다.

🔎 INNER JOIN

두 테이블 간의 일치하는 데이터만 반환합니다. 예: 학생 정보와 학과 정보에서 학생의 학과가 일치하는 데이터만 조회.

-- <JOIN 기본문법>

SELECT *
FROM 테이블1
JOIN 테이블2
ON 테이블1.컬럼 = 테이블2.컬럼;
  • SELECT *
    • 조회할 컬럼을 지정합니다. *은 모든 컬럼을 선택하는 의미입니다. 필요에 따라 테이블1.컬럼, 테이블2.컬럼처럼 특정 컬럼을 지정할 수도 있습니다.
  • FROM 테이블1
    • 첫 번째 테이블을 지정합니다.
  • JOIN 테이블2
    • 두 번째 테이블을 지정합니다. JOIN은 두 테이블을 결합하는 역할을 합니다.
  • ON 테이블1.컬럼 = 테이블2.컬럼
    • ON 절은 두 테이블의 특정 컬럼 값이 일치할 때 해당 레코드를 결합하는 조인 조건을 지정하는 역할을 합니다.

2️⃣ GROUP BY ... HAVING

-- <GROUP BY와 HAVING 기본문법>

SELECT 컬럼1, 집계함수(컬럼2), ...
FROM 테이블명
GROUP BY 그룹화할_컬럼
HAVING 조건;

🔍 GROUP BY

-- 예시: 과목별 평균 점수 조회
SELECT 과목이름, AVG(점수)
FROM 성적
GROUP BY 과목이름;
  • GROUP BY는 SELECT문에서 집계 함수와 함께 사용되어, 특정 컬럼을 기준으로 데이터를 그룹화할 때 사용됩니다.
  • 예를 들어, 과목별 평균 점수를 계산하고 싶다면 GROUP BY 과목이름으로 같은 과목끼리 묶습니다.
  • 그룹화된 각 집단에 대해 SUM, COUNT, AVG, MIN, MAX 같은 집계 함수가 적용됩니다.

🔍 HAVING

-- 예시: 평균 점수가 90 이상인 과목만 조회
SELECT 과목이름, AVG(점수)
FROM 성적
GROUP BY 과목이름
HAVING AVG(점수) >= 90;

 

  • HAVING은 WHERE과 비슷하지만 그룹화된 데이터에 조건을 걸기 위해 사용됩니다.
  • 즉, WHERE은 그룹화 이전의 행 단위 조건, HAVING은 그룹화 이후의 집계 결과 조건입니다.

 


3️⃣ 서브쿼리 (Subquery)

-- <서브쿼리 기본문법>

SELECT 컬럼명
FROM 테이블명
WHERE 컬럼명 비교연산자 (서브쿼리);

서브쿼리(Subquery)는 하나의 SQL문 안에 중첩된 또 다른 쿼리를 의미합니다. 즉, 메인 쿼리(Main Query)가 실행되기 전에 먼저 수행되어, 그 결과값을 메인 쿼리에 제공하는 역할을 합니다. 서브쿼리는 항상 괄호 ()로 감싸서 작성하며, 내부 쿼리부터 먼저 실행됩니다.

서브쿼리는 주로 다음 위치에서 사용됩니다

위치 설명
WHERE 절 특정 조건에 맞는 데이터를 조회할 때 사용됩니다.
FROM 절 서브쿼리 결과를 하나의 테이블처럼 사용합니다.
SELECT 절 서브쿼리 결과를 컬럼처럼 활용합니다.
-- 예: 평균 급여보다 높은 급여를 받는 직원 조회
SELECT 이름, 급여
FROM 사원
WHERE 급여 > (SELECT AVG(급여) FROM 사원);
728x90

📌 문제해설

1️⃣ 메인 쿼리

SELECT count(*)
FROM employee AS e 
JOIN project AS p ON e.project_id = p.project_id
WHERE p.name IN (
    -- (중첩 서브쿼리 생략)
);
  • SELECT count(*)
    • SELECT는 원하는 데이터를 조회할 때 사용하는 SQL 명령어입니다.
    • count(*)는 행(row)의 개수를 세는 집계 함수로, 조건에 부합하는 전체 직원 수를 반환합니다.
    • *는 모든 열을 대상으로 행 개수를 계산한다는 의미입니다. 이 쿼리에서는, 최종적으로 조건에 부합하는 직원 수를 구하려는 목적입니다.
  • FROM employee AS e
    • FROM은 데이터를 가져올 기본 테이블을 지정합니다.
    • 여기서는 employee 테이블을 기준으로 데이터를 조회합니다.
    • AS e는 employee 테이블의 별칭(alias) 을 e로 지정하는 구문입니다. 이후에 employee 대신 e를 사용하여 간결하고 명확하게 컬럼을 참조할 수 있습니다. 예: e.project_id는 employee.project_id를 의미합니다.
  • JOIN project AS p ON e.project_id = p.project_id
    • JOIN은 두 테이블을 연결(조인)하는 SQL 문입니다.
    • INNER JOIN이 생략된 형태이며, 기본적으로 일치하는 행만 반환합니다.
    • employee 테이블(e)과 project 테이블(p)을 project_id 기준으로 연결합니다.
    • AS p는 project 테이블의 별칭(alias) 을 p로 지정합니다. 이후에 project 대신 p를 사용하여 컬럼을 간단히 참조합니다. 예: p.name는 project.name을 의미합니다.
  • WHERE p.name IN (...)
    • WHERE 절은 필터 조건을 지정합니다.
    • 이 조건을 만족하는 행만 count(*)의 대상이 됩니다.
    • p.name IN (...)은 project.name이 괄호 안 서브쿼리 결과와 일치하는 경우만 선택합니다. 즉, 특정 조건을 만족하는 프로젝트 이름에 속한 직원만 카운트합니다.

2️⃣ 서브 쿼리

WHERE p.name IN (
    SELECT name
    FROM project p
    WHERE p.project_id IN (
        SELECT project_id
        FROM employee
        GROUP BY project_id
        HAVING count(*) < 2
    )
);

이 서브쿼리는 총 3단계 중첩 구조로 되어 있으며, 안쪽 → 바깥쪽 순서로 실행됩니다.

🔍 1단계: 가장 안쪽 서브쿼리

SELECT project_id
FROM employee
GROUP BY project_id
HAVING count(*) < 2

 

  • employee 테이블에서 project_id를 기준으로 그룹화하고, 각 프로젝트에 배정된 직원 수가 2명 미만인 project_id만 추출합니다.
  • project_id = 20만 조건에 만족합니다 (< 2)

 

🔍 2단계: 중간 서브쿼리

SELECT name
FROM project p
WHERE p.project_id IN ( ... )


-- SELECT name
-- FROM project p
-- WHERE p.project_id IN (20)
  • 이 쿼리는 project 테이블에서 지정된 project_id 값과 일치하는 행을 찾고, 해당 행의 name 컬럼 값을 조회합니다.
  • WHERE IN 구문을 사용하여 서브쿼리의 결과값에 포함된 project_id와 일치하는 데이터만 조회할 수 있습니다.
  • 서브쿼리 결과가 20이므로, project 테이블에서 project_id = 20인 행을 찾아 name = 'Beta'를 반환합니다

🔍 3단계: 바깥쪽 메인 쿼리의 WHERE 조건

SELECT count(*)
FROM employee AS e JOIN project AS p ON e.project_id = p.project_id
WHERE p.name IN (...);


-- SELECT count(*)
-- FROM employee AS e JOIN project AS p ON e.project_id = p.project_id
-- WHERE p.name IN ('Beta')
  • AS를 사용해 employee 테이블을 e라는 별칭으로 project 테이블도 p라는 별칭으로 간단히 표현합니다. 별칭을 사용하면 긴 테이블명을 반복하지 않아도 되어 가독성 향상에 유리합니다.
  • 메인 쿼리는 employee 테이블과 project 테이블을 project_id를 기준으로 조인(JOIN)한 뒤, project.name이 'Beta'인 행들만 필터링합니다.
  • 즉, 직원이 2명 미만인 프로젝트(앞 단계에서 name = 'Beta'로 확인됨) 에 배정된 직원 수를 셉니다. 만족하는 행은 단 1개.

 


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

728x90
반응형