SQL 코드카타
문제 44
가격대별 상품 개수 구하기
PRODUCT 테이블에서 만원 단위의 가격대 별로 상품 개수를 출력하는 SQL문을 작성해주세요. 이때 컬럼명은 각각 PRICE_GROUP, PRODUCT로 지정해 주시고 가격대 정보는 각 구간의 최소금액(10,000원 이상~20,000원 미만인 구간인 경우 10,000)으로 표시해 주세요. 결과는 가격대 기준으로 오름차순 정렬해주세요.
처음 답안
SELECT CASE WHEN PRICE >= 0 AND PRICE < 10000 THEN 0
WHEN PRICE >= 10000 AND PRICE < 20000 THEN 10000
WHEN PRICE >= 20000 AND PRICE < 30000 THEN 20000
ELSE 30000 END AS PRICE_GROUP, -- 30000 이상인 구간부터는 만 원 단위로 나누지 않음
COUNT(PRODUCT_ID) AS PRODUCTS
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP;
최종 답안
SELECT CASE WHEN PRICE >= 0 AND PRICE < 10000 THEN 0
WHEN PRICE >= 10000 AND PRICE < 20000 THEN 10000
WHEN PRICE >= 20000 AND PRICE < 30000 THEN 20000
WHEN PRICE >= 30000 AND PRICE < 40000 THEN 30000 -- 30000 이상인 구간도 만 원 단위로 나눔
WHEN PRICE >= 40000 AND PRICE < 50000 THEN 40000
WHEN PRICE >= 50000 AND PRICE < 60000 THEN 50000
WHEN PRICE >= 60000 AND PRICE < 70000 THEN 60000
WHEN PRICE >= 70000 AND PRICE < 80000 THEN 70000
WHEN PRICE >= 80000 AND PRICE < 90000 THEN 80000
END AS PRICE_GROUP,
COUNT(PRODUCT_ID) AS PRODUCTS
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP;
틀린 이유
문제에서 '만 원 단위의 구간'으로 나누라는 조건 주었다.
일부 구간만 만 원 단위로 나누고, 일부 구간은 나누지 않았다.
개선점
문제의 조건을 정확하게 파악하자.
이 문제는 모든 구간을 만 원 단위로 나누어야 한다.
문제 51
없어진 기록 찾기
입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.
처음 답안 (틀림)
SELECT I.ANIMAL_ID, -- I 테이블
I.NAME -- I 테이블
FROM ANIMAL_INS I
LEFT JOIN ANIMAL_OUTS O -- I 테이블 기준 LEFT JOIN
ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE O.DATETIME IS NOT NULL
AND I.DATETIME IS NULL
ORDER BY I.ANIMAL_ID;
최종 답안
SELECT O.ANIMAL_ID, -- O 테이블
O.NAME -- O 테이블
FROM ANIMAL_INS I
RIGHT JOIN ANIMAL_OUTS O -- O 테이블 기준 RIGHT JOIN
ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE O.DATETIME IS NOT NULL
AND I.DATETIME IS NULL
ORDER BY I.ANIMAL_ID;
틀린 이유
LEFT JOIN 시, 어떤 테이블을 기준으로 할지 헷갈렸다.
문제의 조건에서
입양을 간 기록은 있는데, → O 테이블
보호소에 들어온 기록은 없음 → I 테이블
≫ O 테이블 기준으로 LEFT JOIN
개선점
LEFT JOIN
- 어떤 테이블을 기준으로 할 것인가?
즉, 두 테이블 중 어떤 테이블의 전체를 가져올 것인가?
- 기준이 되는 테이블을 FROM절의 왼쪽에 쓰기
Python 알고리즘 코드카타
문제 27
핸드폰 번호 가리기
처음 답안
def solution(phone_number):
n = len(phone_number)
num1 = phone_number[:n-4]
num2 = phone_number[n-4:n]
answer = ''
for i in range(len(num1)):
answer += '*'
for i in range(len(num2)):
answer += num2[i]
return answer
최종 답안
def solution(phone_number):
n = len(phone_number)
answer = ''
answer += '*'*(n-4) # '*'을 (n-4)번 반복
answer += phone_number[n-4:n]
return answer
개선점
1. 문자열(string)에 곱셈(*) 사용하여 반복 가능
예시
'string' * 4
> stringstringstringstring
'*' * 5
> *****
2. 문자열(string) 인덱싱, 슬라이싱 가능
- 인덱싱, 슬라이싱 가능한 것: 문자열, 리스트, 튜플 등
아티클 스터디
[아티클]
양질의 데이터를 판별하는 5가지 방법: 1 데이터 양은 충분한가?
https://yozm.wishket.com/magazine/detail/1070/
[요약]
수집된 데이터를 모두 활용할 수는 없다. 양질의 데이터를 판별하는 것이 필요하다.
1. 양질의 데이터란 무엇인가?
1) 데이터의 품질
데이터의 품질이 높을수록 활용 가치가 높다. 데이터가 명확하고 깔끔하고 해석이 용이하기 때문이다. 저품질의 데이터라도 꼭 필요하다면 가공, 보완한 뒤 활용할 수 있다. 다만 고품질의 데이터일수록 실제로 활용될 가능성이 높다.
데이터 중 활용 가능성이 현저히 낮은 저품질 데이터가 많다. 그러므로 데이터를 무작정 많이 수집하는 것은 비효율적이다. 양질의 데이터를 판별할 줄 알면, 데이터 수집과 분석의 효율성을 제고할 수 있다. 활용 가치가 없거나 활용하기에 어려움이 많은 데이터는 애초에 수집하거나 분석하지 않는 것이다.
2) 양질의 데이터를 판단하는 방법
데이터 품질을 파악하기 위해 두 가지 질문을 할 수 있다.
분석을 하기 쉬운 데이터인가?
이 데이터로 분석을 하면 결과를 명확하게 받아들일 수 있는가?
양질의 데이터를 분석에 유리한 데이터라고 정의한다면, 양질의 데이터는 보통 5가지 특징이 있다.
① 데이터의 수가 충분히 많다.
② 데이터 자체의 오류가 적다.
③ 관계형 데이터베이스 형식을 잘 지키고 있다.
④ 수치형 데이터 형식을 많이 보유하고 있다.
⑤ 활용 목적에 적합하다.
2. 양질의 데이터의 조건 첫 번째: 충분한 양의 데이터
데이터의 양이 중요한 상황이 언제인지,
충분한 양의 데이터란 어느 정도의 양인지 답할 수 있어야 한다.
1) 데이터 양을 중요하게 고려해야 하는 경우
① 표본이 모집단을 대표하지 못할 때
데이터 수가 너무 적으면 표본의 대표성이 보장되지 않을 수 있다.
② AI 알고리즘 적용해야 하는 경우
딥러닝 알고리즘은 데이터가 많을수록 AI 정확도가 높아진다.
데이터의 양이 일정 수준에 미치지 못하면 AI 알고리즘을 적용하기 어렵다.
2) 어느 정도의 데이터가 충분한 양인가?
명확한 분류 방법과 절대적인 기준은 없다.
① 통계적 분석
최소 500개 이상의 데이터
② 머신 러닝
변수의 수에 100을 곱한 것보다 많은 양의 데이터
데이터의 양은 분석 결과의 신뢰도와 연관된다.
[핵심 개념 및 용어 정리]
1. 관계형 데이터베이스 형식
데이터를 행과 열로 구성하는 데이터베이스 유형
데이터 포인트가 서로 관련된 테이블을 집합적으로 형성한다.
데이터는 일반적으로 여러 테이블에 걸쳐 구성되며, 기본 키나 외래 키를 통해 함께 조인될 수 있다.
2. 수치형 데이터 형식
numerical data
관측된 값이 수치, 즉 숫자 형태로 표현되는 데이터를 말한다.
https://bekoinny.tistory.com/69
https://m.blog.naver.com/cslee_official/222207347506
[인사이트]
데이터 수집 단계에서도 분석가의 가치 판단이 개입될 수 있다는 것을 알았다. '어떤 데이터가 양질의 데이터인가?'를 기준으로 특정 데이터를 아예 수집하지 않을 수 있다는 것이다. 처음에는 데이터 분석 프로세스 중 '분석' 과정 위주로 분석가의 주관이 반영된다고 생각했다. 여러 아티클을 읽으며 데이터 분석가가 데이터 분석 프로세스의 거의 전 과정에서 가치 판단을 하고, 이를 바탕으로 업무를 한다는 것을 알게 되었다.
SQLD 헷갈리는 내용만 정리 (Oracle)
참고 자료
SQL 자격검정 실전문제, 한국데이터산업진흥원
GPT 검색
GROUP BY가 있는 쿼리에서 ORDER BY에 쓸 수 있는 항목
1. SELECT에 있는 컬럼 또는 표현식
2. GROUP BY에 있는 컬럼
3. 집계 함수
NULLIF(표현식1, 표현식2)
표현식1과 표현식2가 같으면 NULL
아니면 표현식1 리턴
COALESCE(A, B)
NULL아니면 A 반환
NULL이면 B 반환
NVL(A, B)
A가 NULL이 아니면 A 반환
A가 NULL이면 B 반환
JOIN
DBMS 옵티마이저는 FROM 절에 나열된 테이블을 2개씩 짝지어 JOIN 수행
EQUI JOIN은 테이블 간 컬럼 값이 정확하게 일치할 때 사용
EQUI JOIN = 연산자 사용, 그 이외 비교 연산자 사용하면 모두 NON EQUI JOIN
대부분 NON EQUI JOIN 수행가능, 때로는 설계상 이유로 수행 불가능하기도
적절한 JOIN 조건이 없으면 (공통 컬럼 없으면) 카티시안 곱 발생
순수 관계 연산자
SELECT, PROJECT, JOIN, DIVIDE
CROSS JOIN
두 테이블의 모든 행 조합 만들어내는 JOIN
카티시안 곱이라고도 함
FROM A, B
FROM A CROSS JOIN B
FULL OUTER JOIN
좌측 우측 테이블의 모든 데이터 읽어 JOIN하여 결과 생성
LEFT JOIN과 RIGHT JOIN 결과의 합집합(UNION)
ORACLE JOIN 문법 ANSI 문법으로 바꾸기
ORACLE: (+)가 붙은 조건은 JOIN
WHERE A.ID = B.ID(+) → A 기준으로 B를 OUTER JOIN (즉, LEFT OUTER JOIN)
AND B.삭제여부(+) = 'N' → OUTER JOIN 조건 안에 포함
AND A.사용여부 = 'Y' → WHERE 필터 조건
ANSI
WHERE A.ID = B.ID(+) → LEFT JOIN
AND B.삭제여부(+) = 'N' → ON절에 포함
AND A.사용여부 = 'Y' → WHERE절에
다중 컬럼 서브쿼리
서브쿼리의 실행 결과로 여러 컬럼을 반환한다.
비교하고자 하는 컬럼 개수와 컬럼 위치가 동일해야 한다.
집합 연산자
UNION: 합집합
UNION ALL: 합집합이면서 중복된 행도 그대로 표시
INTERSECT: 교집합
EXCEPT: 차집합 (일부 DB는 MINUS)
차이 알기
GROUPING SETS: 내가 원하는 그룹 조합 직접 지정
ROLLUP: 위-아래 방향 누적 집계
CUBE: 모든 조합에 대해 집계
GROUPING SETS (A, (B, A)): A / B, A
ROLLUP(A, B): A, B / A / 전체 → 이것만 다름
A, ROLLUP(B): A, B / A, NULL
A, CUBE(B): A, B / A, NULL
'양쪽 필수 관계 시스템적으로 보장될 때'의 의미
양쪽 모두 null이 허용되지 않고, 반드시 연결되어 있어야 함
계층형 구조
하나의 테이블에 부모-자식 관계가 있는 구조
계층형 질의
계층형 구조를 가진 데이터를 계층적 순서대로 조회하는 문법
보통 START WITH 와 CONNECT BY 절을 사용해 부모-자식 관계를 따라가면서 데이터를 계층적으로 조회
예시
SELECT employee_id, manager_id, employee_name, LEVEL
FROM employees
START WITH manager_id IS NULL -- 최상위 노드 지정 (예: 사장)
CONNECT BY PRIOR employee_id = manager_id; -- 부모-자식 관계 지정
- START WITH: 계층의 시작점(루트)을 지정
- CONNECT BY PRIOR: 부모와 자식 관계를 정의 (여기서 PRIOR은 한 단계 위(부모)를 가리킴)
- LEVEL: 현재 노드의 깊이(루트부터 몇 번째 단계인지)를 나타내는 가상 컬럼
오라클 계층형 질의 선지
START WITH: 계층 구조 시작점 지정하는 구문
ORDER SIBLINGS BY: 형제 노드 사이에서 정렬을 지정하는 구문
순방향전개: 부모 노드로부터 자식 노드로 전개
루트 노드: LEVEL 1
오라클 문자열 연결 연산자
||
두 문자열 이어붙일 때 사용
다른 언어의 +와 비슷
HAVING
GROUP BY나 집계 함수 사용하지 않고 HAVING 절 사용했다고 해서 SQL문장 오류 발생하지 않는다.
SQL 문법에서 HAVING은 두 경우가 가능
1. GROUP BY가 있을 때 → 각 그룹에 조건
2. GROUP BY가 없을 때 → 전체 결과(단일 그룹)에 조건
서브쿼리 종류
단일행 연관 서브쿼리 | 1개 | O | WHERE | =, >, < |
인라인 뷰 | 여러 행 | X | FROM | 없음 (별칭만 필요) |
다중행 연관 서브쿼리 | 여러 행 | O | WHERE | IN, EXISTS, ALL |
뷰
독립성: 테이블 구조가 변경되어도 뷰를 사용하는 응용 프로그램은 변경하지 않아도 된다.
편리성: 복잡한 질의를 뷰로 생성해 관련 질의 단순하게 작성할 수 있다.
보안성: 숨기고 싶은 정보는, 뷰를 생성할 때 해당 컬럼 빼고 생성해 감출 수 있다.
정의만 가지고 있음
실행 시점에 질의 재작성하여 수행
실제 데이터를 저장하고 있는 뷰를 생성하는 기능 지원하는 DBMS도 있음
윈도우 함수
형식
함수명() OVER (
PARTITION BY 컬럼명 -- 그룹 나누기
ORDER BY 컬럼명 -- 정렬 기준 (순위 등)
)
자주 나오는 함수
ROW_NUMBER() | 파티션 안에서 정렬 기준에 따라 순번 부여 (중복 없음) |
RANK() | 동일한 값은 동일 순위 부여, 다음 순위는 건너뜀 (1, 1, 3, 4...) |
DENSE_RANK() | 동일한 값은 동일 순위, 다음 순위는 바로 다음 숫자 (1, 1, 2, 3...) |
SUM() | 누적합 계산 |
AVG() | 누적 평균 계산 |
MAX() / MIN() | 누적 최대/최소값 |
COUNT() | 누적 개수 |
LAG() | 이전 행의 값 가져오기 |
LEAD() | 다음 행의 값 가져오기 |
NTILE(n) | 파티션을 n개의 동일한 그룹으로 나눔 (예: 사분위수) |
출제빈도
ROW_NUMBER() | 정렬 기준으로 순번 | 🔥 매우 자주 |
RANK(), DENSE_RANK() | 순위 매기기 | 🔥 매우 자주 |
SUM(), AVG() | 누적합, 평균 | 🔥 매우 자주 |
MAX(), MIN() | 누적 최대, 최소 | 🔥 자주 출제 |
LAG(), LEAD() | 이전/다음 행 비교 | ⚠️ 가끔 출제 |
NTILE(n) | 그룹 나누기 | ⚠️ 가끔 출제 |
CUBE
결합 가능한 모든 값에 대하여 다차원 집계 생성