관리 메뉴

한다 공부

[MySQL] SQL 문법 정리 & 문제풀이 (30문제) 본문

CS/SQL

[MySQL] SQL 문법 정리 & 문제풀이 (30문제)

사과당근 2023. 5. 2. 03:26

SQL 문법을 자꾸 깜빡해서..

꾸준히 보면서 복습하려고 정리해봤습니다 ..~

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

... 위 코스를 따라가며 문제를 풀었습니다 ..~

 

1. SELECT

2. SUM, MAX, MIN

3. GROUP BY

4. IS NULL

5. JOIN

6. String, Date

 


1. SELECT

SELECT 칼럼
FROM 테이블
WHERE 조건
ORDER BY 정렬기준;

- 모든 레코드 조회하기

ANIMAL_INS 테이블의 모든 데이터를 ID 순으로 오름차순하며 조회

SELECT *
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

- 역순 정렬하기

위와 마찬가지지만, ID를 기준으로 내림차순 정렬했으며 전체 데이터가 아닌 NAME, DATETIME만 조회

SELECT NAME, DATETIME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID DESC;

- 아픈 동물 찾기

동물을 ID 오른차순으로 정렬, 상태가 Sick인 동물만, ID와 NAME을 조회

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION='Sick'
ORDER BY ANIMAL_ID;

- 어린 동물 찾기

위와 마찬가지, 하지만 조건이 Aged (늙은) 가 아닌 동물 조회

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION != 'Aged'
ORDER BY ANIMAL_ID;

- 동물의 아이디와 이름

ID 기준 오름차순 정렬, ID와 이름만 조회

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

- 여러 기준으로 정렬하기

정렬 조건이 2개, ASC (오름차순)의 경우 따로 명시하지 않아도 됨, 이름이 같다면 늦은 날짜를 먼저 조회

SELECT ANIMAL_ID, NAME, DATETIME
FROM ANIMAL_INS
ORDER BY NAME, DATETIME DESC;

- 상위 n개 레코드

LIMIT n 하면 상위 n개의 데이터 조회 가능, 아래 코드는 가장 먼저 보호소에 들어온 동물 한 마리의 이름을 조회

SELECT NAME
FROM ANIMAL_INS
ORDER BY DATETIME
LIMIT 1;

- 조건에 맞는 회원수 구하기

칼럼 별칭은 USERS, USER_INFO 테이블에서, 2021년 이전에 가입힌 20~29세 회원 몇 명인지 조회

SELECT COUNT (*) AS USERS
FROM USER_INFO
WHERE YEAR(JOINED)=2021 AND AGE<=29 AND AGE>=20;

 


2. SUM, MAX, MIN

SELECT MAX(칼럼)
FROM 테이블;

- 가격이 제일 비싼 식품의 정보 출력하기

MAX(PRICE)를 하면 가장 가격이 높은 상품의 '가격'만 조회,

따라서 가장 가격이 높은 상품의 '가격 '과 같은 가격을 가진 상품을 SELECT 하면, 가장 높은 가격을 가진 상품의 모든 레코드가 조회됨

SELECT *
FROM FOOD_PRODUCT
WHERE PRICE = (SELECT MAX(PRICE) FROM FOOD_PRODUCT);

- 최댓값 구하기

칼럼 명은 시간으로, 가장 최근에 보호소에 들어온 동물 조회

SELECT MAX(DATETIME) AS 시간
FROM ANIMAL_INS;

- 최솟값 구하기

위와 마찬가지지만, 가장 먼저 보호소에 들어온 동물 조회

SELECT MIN(DATETIME) AS 시간
FROM ANIMAL_INS;

- 동물 수 구하기

모든 동물 수 구하기

SELECT COUNT(*) AS count
FROM ANIMAL_INS;

- 중복 제거하기

이름이 중복되지 않는 동물들이 총 마리인지 구하기

SELECT COUNT(DISTINCT(NAME)) AS count
FROM ANIMAL_INS;

 


3. GROUP BY

SELECT 칼럼
FROM 테이블
WHERE 조건
GROUP BY 칼럼
HAVING 그룹 조건
ORDER BY 정렬기준;

- 고양이와 개는 몇 마리 있을까

동물 타입 별로 그룹화하기 (고양이 별 & 강아지 별), 그리고 그룹에 몇 마리가 속해 있는지 계산

SELECT ANIMAL_TYPE, COUNT(*) AS count
FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE;

- 동명 동물 수 찾기

동물 이름 별로 그룹화하기, 그리고 그룹에 몇 마리가 속해 있는지 계산

단, 이름이 없는 동물은 집계 X, 그리고 두 번 이상 쓰인 이름만 집계

SELECT NAME, COUNT(*) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT(NAME) > 1
ORDER BY NAME;

- 입양 시각 구하기

DATETIME에서 시간을 뽑아와서 그룹화, 09:00 ~ 19:59 사이 입양이 몇 건 발생했는지 조회

SELECT HOUR(DATETIME) AS HOUR, COUNT(*) AS COUNT
FROM ANIMAL_OUTS
GROUP BY HOUR
HAVING HOUR>=9 AND HOUR<20
ORDER BY HOUR;

- 진료과별 총 예약 횟수 출력하기

진료과코드 별 2022-05월 예약건수 계산

select 절의 alias를 where, having 에서 사용할 수 없고 order by 에서는 사용할 수 있다는 것을 봤는데 MySQL에서는 where, having 절에서도 가능하다고 한다.

왜 2022-05라는 조건이 having에 안 들어가고 where에 들어갔냐면 having은 그룹을 나타내는 결과 집합의 칼럼에만 적용되고, where 절은 개별 행에 적용되기 때문이다.

SELECT MCDP_CD AS 진료과코드, COUNT(*) AS 5월예약건수
FROM APPOINTMENT
WHERE YEAR(APNT_YMD)=2022 AND MONTH(APNT_YMD)=5
GROUP BY MCDP_CD
ORDER BY 5월예약건수, 진료과코드;

 


4. IS NULL

SELECT 칼럼
FROM 테이블
WHERE 칼럼 IS NULL;
# 혹은
SELECT 칼럼
FROM 테이블
WHERE 칼럼 IS NOT NULL;

- 이름이 없는 동물의 아이디

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NULL;

- 이름이 있는 동물의 아이디

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NOT NULL;

- NULL 처리하기

1. SQL에서 쌍따옴표보다 따옴표를 사용하자 (MySQL은 둘 다 가능한 듯)

2. IFNULL(A,B) : MySQL에서 사용, A 컬럼의 데이터 중 NULL인 것이 있으면 B로 변경

ㄴ MSSQL에서는 ISNULL(A,B)

ㄴ Oracle에서는 NVL(A,B)

3. [참고] NULLIF(A,B) : A==B이면 NULL을 반환, A!=B이면 A리턴

SELECT ANIMAL_TYPE, IFNULL(NAME,'No name') AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS;

- 나이 정보가 없는 회원 수 구하기

SELECT COUNT(*) AS USERS
FROM USER_INFO
WHERE AGE IS NULL;

 


5. JOIN

참고용 사진


- 없어진 기록 찾기

보호소에서 나간 기록은 있으나, 들어온 기록은 유실된 상황

따라서 나간 테이블을 기준으로 RIGHT JOIN을 하고, 유실 데이터를 찾기 위해 들어온 기록이 NULL인 데이터 조회

SELECT AO.ANIMAL_ID, AO.NAME
FROM ANIMAL_INS AS AI RIGHT JOIN ANIMAL_OUTS AS AO
ON AI.ANIMAL_ID=AO.ANIMAL_ID
WHERE AI.ANIMAL_ID IS NULL
ORDER BY ANIMAL_ID;

- 있었는데요 없었습니다

JOIN 한 뒤, 보호 시작일이 더 빠른 잘못된 데이터들을 조회

SELECT AI.ANIMAL_ID, AI.NAME
FROM ANIMAL_INS AS AI JOIN ANIMAL_OUTS AS AO
ON AI.ANIMAL_ID=AO.ANIMAL_ID
WHERE AI.DATETIME>AO.DATETIME
ORDER BY AI.DATETIME;

- 오랜 기간 보호한 동물(1)

입양 못 간 동물들 중 가장 오래 보호한 동물 3마리를 조회

AO 테이블에는 입양 간 동물들의 데이터 존재

SELECT AI.NAME, AI.DATETIME
FROM ANIMAL_INS AS AI LEFT JOIN ANIMAL_OUTS AS AO
ON AI.ANIMAL_ID=AO.ANIMAL_ID
WHERE AO.ANIMAL_ID IS NULL
ORDER BY AI.DATETIME
LIMIT 3;

- 보호소에서 중성화한 동물

입양 전에는 중성화되어있지 않고, 입양 후에는 중성화 된 동물 찾기

성별 데이터에 Spayed와 Neutered가 있으면 중성화 되어있다는 뜻

SELECT AO.ANIMAL_ID, AO.ANIMAL_TYPE, AO.NAME
FROM ANIMAL_INS AS AI RIGHT JOIN ANIMAL_OUTS AS AO
ON AI.ANIMAL_ID=AO.ANIMAL_ID
WHERE
    (AI.SEX_UPON_INTAKE NOT LIKE '%Spayed%' AND AI.SEX_UPON_INTAKE NOT LIKE '%Neutered%')
    AND
    (AO.SEX_UPON_OUTCOME LIKE '%Spayed%' OR AO.SEX_UPON_OUTCOME LIKE '%Neutered%')
ORDER BY AO.ANIMAL_ID;

 


6. String, Date

조건을 추가할 수 있는데, 아래 두 개의 조건문을 사용할 수 있다.

SELECT IF(조건, True일 때 값, False일 때 값)
FROM 테이블;

 

SELECT
    CASE
        WHEN 조건
        THEN 값
        WHEN 조건
        THEN 값
        ELSE 값
    END
FROM 테이블;

- 루시와 엘라 찾기

WHERE 칼럼 IN(리스트) : 칼럼에 있는 데이터 중, 리스트 안의 값과 동일한 값을 가진 데이터만 조회

SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
WHERE NAME IN('Lucy', 'Ella', 'Pickle', 'Rogan', 'Sabrina', 'Mitty');

- 이름에 el 들어가는 동물 찾기

이름에 el이 들어가고 Dog 인 동물 조회

% : 글자수 제한 없음, e%면 e, er, ert, erty, ertyu ... 모두 조회

_ : 언더바 갯수 만큼 글자수 제한 있음, e_면 er, et, ey, eu ... 등 조회

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE NAME LIKE '%el%' AND ANIMAL_TYPE='Dog'
ORDER BY NAME;

- 중성화 여부 파악하기

IF(조건문, 값1, 값2) : 조건문에 해당하면 값1, 아니면 값2

SELECT ANIMAL_ID, NAME,
IF(SEX_UPON_INTAKE LIKE '%Neutered%' OR
   SEX_UPON_INTAKE LIKE '%Spayed%', 'O', 'X') AS 중성화
FROM ANIMAL_INS;

- 오랜 기간 보호한 동물(2)

두 테이블을 JOIN한 뒤, 입양 보낸 기간 - 보호소에 들어온 기간을 내림차순 하고 상위 2 마리를 조회

SELECT AI.ANIMAL_ID, AI.NAME
FROM ANIMAL_INS AS AI JOIN ANIMAL_OUTS AS AO
WHERE AI.ANIMAL_ID=AO.ANIMAL_ID
ORDER BY AO.DATETIME-AI.DATETIME DESC
LIMIT 2;

아래와 같이 ON절을 사용해도 정답이다.

SELECT AI.ANIMAL_ID, AI.NAME
FROM ANIMAL_INS AS AI JOIN ANIMAL_OUTS AS AO
ON AI.ANIMAL_ID=AO.ANIMAL_ID
ORDER BY AO.DATETIME-AI.DATETIME DESC
LIMIT 2;

- DATETIME에서 DATE로 형 변환

DATE_FORMAT(날짜 칼럼, "원하는 표기 형태") : 날짜 표기 방법을 변환

SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME, "%Y-%m-%d") AS 날짜
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

 

'CS > SQL' 카테고리의 다른 글

[MySQL] SQL 문제풀이 (String, Date)  (1) 2023.12.23
[MySQL] SQL 문제풀이 (JOIN)  (2) 2023.11.07
[MySQL] SQL 문제풀이 (GROUP BY)  (1) 2023.10.27
[MySQL] SQL 문제풀이 (SELECT)  (0) 2023.10.25
[MySQL] SQL 문제풀이 (6문제)  (0) 2023.09.18