본문 바로가기

CSあるある

JOIN 테이블에 대한 UPDATE문 동작 원리

1. 예제 테이블 준비

employees (직원 정보) 테이블

id name salary

1 홍길동 500만원
2 김철수 550만원
3 이영희 600만원

projects (프로젝트 정보) 테이블

project_id employee_id status

101 1 진행 중
102 1 진행 중
103 2 진행 중
104 3 완료됨

위 테이블에서 employees와 projects를 JOIN해서 진행 중(status = '진행 중')인 직원들의 급여를 100만 원 올리는 UPDATE 쿼리를 실행한다고 해보자.


2. 문제의 쿼리

UPDATE employees e
JOIN projects p ON e.id = p.employee_id
SET e.salary = e.salary + 100000
WHERE p.status = '진행 중';

이 UPDATE 문이 실행되면 JOIN 결과는 다음과 같이 중복될 수 있어.

JOIN 결과:

e.ide.namee.salaryp.project_idp.status

1 홍길동 500만원 101 진행 중
1 홍길동 500만원 102 진행 중
2 김철수 550만원 103 진행 중

여기서 홍길동(직원 id=1)JOIN 결과에 두 번 등장(중복)한다.


하지만 실제 UPDATE는 같은 직원의 급여를 한 번만 올린다(이 원리에 대해서는 밑에서 설명)

즉, 홍길동이 JOIN 결과에서 2번 나왔다고 해서 급여가 2번(20만 원) 오르는 게 아니라 1번(10만 원)만 오른다.


3. UPDATE 실행 후 결과

idnamesalary

1 홍길동 600만 원 (500 + 100)
2 김철수 650만 원 (550 + 100)
3 이영희 600만 원 (변경 없음)
  • 홍길동은 JOIN 결과에서 두 번 등장했지만, UPDATE는 한 번만 적용되어 급여가 10만 원만 증가
  • 김철수도 한 번 등장하므로 급여가 10만 원 증가
  • 이영희는 진행 중인 프로젝트가 없어서 변경 없음

4. 문제점: 원하는 만큼 업데이트되지 않을 수 있음

만약 "홍길동은 진행 중인 프로젝트 2개가 있으니까 급여를 20만 원 올리고 싶다!" 라면, 위 방식은 잘못된 거야.
이럴 때는 중복 개수를 고려한 업데이트를 해야 해.

해결 방법: GROUP BY를 사용해 중복을 줄이고 프로젝트 개수만큼 급여 증가시키기

UPDATE employees e
JOIN (
    SELECT employee_id, COUNT(*) AS project_count
    FROM projects
    WHERE status = '진행 중'
    GROUP BY employee_id
) p ON e.id = p.employee_id
SET e.salary = e.salary + (100000 * p.project_count);
 

이렇게 하면 홍길동의 급여는 20만 원, 김철수는 10만 원 증가!

idnamesalary

1 홍길동 700만 원 (500 + 200)
2 김철수 650만 원 (550 + 100)
3 이영희 600만 원 (변경 없음)

5. 결론

✅ UPDATE 문은 같은 행이 JOIN 결과에서 여러 번 나와도, 그 행이 한 번만 업데이트됨
JOIN 결과의 중복을 고려하지 않으면 원하는 만큼 업데이트되지 않을 수도 있음
✅ 원하는 만큼 업데이트하려면 GROUP BY로 중복을 처리한 후, 적절한 값(예: 프로젝트 개수)을 계산하여 반영해야 함

 

Q. DB는 어떻게 해서 중복된 행인지 알아 내는 걸까?

결론 : DBMS는 UPDATE 문이 실행될 때 각 행(row)의 기본 키(Primary Key) 또는 유니크한 식별자를 기반으로

중복을 판별.

자세한 과정을 아래에서 설명

1. UPDATE 실행 시 DBMS 내부 동작

UPDATE 문을 실행하면 다음 과정이 이루어져:

  1. FROM이나 JOIN을 수행하여 대상 행을 찾음
    • JOIN이 포함된 UPDATE라면, 여러 테이블을 조인한 결과를 먼저 생성해.
  2. WHERE 절을 평가하여 업데이트할 행을 필터링
    • WHERE 조건을 만족하는 행만 선택됨.
  3. 업데이트할 행을 Primary Key 기준으로 식별
    • 같은 id(또는 유니크한 값)를 가진 행이 JOIN 결과에서 여러 번 등장하더라도, DB는 해당 id를 가진 행을 한 번만 업데이트
  4. SET 절을 실행하여 선택된 행의 값을 변경
    • 각 행이 업데이트될 때, JOIN 결과에서 여러 번 나와도 한 번만 적용됨.

2. 중복 판별 과정 예제

📌 테이블 예제

employees (직원 정보)

id name salary

1 홍길동 500만원
2 김철수 550만원

projects (프로젝트 정보)

project_id employee_id status

101 1 진행 중
102 1 진행 중
103 2 진행 중

📌 실행할 UPDATE 문

UPDATE employees e
JOIN projects p ON e.id = p.employee_id
SET e.salary = e.salary + 100000
WHERE p.status = '진행 중';
 

📌 JOIN 결과 (업데이트 대상 행)

e.ide.namee.salaryp.project_idp.status

1 홍길동 500만원 101 진행 중
1 홍길동 500만원 102 진행 중
2 김철수 550만원 103 진행 중

🔍 DBMS가 UPDATE를 실행하는 방식

  1. JOIN 결과를 생성했을 때, 홍길동(id=1) 이 두 번 등장
  2. 하지만 UPDATE 시, DB는 employees.id (기본 키)를 기준으로 업데이트할 행을 찾음
  3. 홍길동(id=1)의 급여를 한 번만 업데이트 (500 → 600만 원)
  4. 김철수(id=2)도 한 번 업데이트 (550 → 650만 원)

결과 테이블

id name salary

1 홍길동 600만 원 (500 + 100)
2 김철수 650만 원 (550 + 100)

3. 중복된 행을 식별하는 핵심 원리

💡 DBMS는 각 행을 업데이트할 때 "고유한 식별자(Primary Key)"를 기준으로 한 번만 적용한다.
💡 JOIN에서 동일한 id가 여러 번 나와도, 기존 테이블(employees)에서 같은 id를 가진 행을 한 번만 업데이트한다.

📌 만약 Primary Key가 없다면?

기본 키 없이 UPDATE를 수행하면 DB가 어떤 행을 업데이트해야 할지 애매해질 수도 있어.
이 경우, 중복된 레코드가 있는 테이블이라면 예상치 못한 결과가 나올 수도 있어.
따라서, 항상 Primary Key가 있는지 확인하는 것이 중요해!


4. 중복을 활용해서 업데이트하려면?

만약 JOIN 결과에서 중복된 횟수만큼 업데이트하고 싶다면, GROUP BY나 COUNT()를 활용하면 돼.

UPDATE employees e
JOIN (
    SELECT employee_id, COUNT(*) AS project_count
    FROM projects
    WHERE status = '진행 중'
    GROUP BY employee_id
) p ON e.id = p.employee_id
SET e.salary = e.salary + (100000 * p.project_count);

✔ COUNT(*)를 사용하여 중복 개수만큼 급여를 증가시킬 수 있음.

결과

idnamesalary

1 홍길동 700만 원 (500 + 200)
2 김철수 650만 원 (550 + 100)

5. 정리

  • UPDATE는 기본 키(Primary Key)를 기준으로 중복을 판별하며, 같은 행을 한 번만 업데이트함.
  • JOIN 결과에서 동일한 행이 여러 번 나와도, 실제 UPDATE에서는 중복 적용되지 않음.
  • 중복된 횟수만큼 업데이트하려면 GROUP BY를 활용하여 사전에 개수를 계산해야 함.