SQL
USE sakila;
select actor_id, last_update from actor
limit 10;
limit 절
- limit 보여줄 데이터 수(행)
- limit는 변환되는 데이터의 개수를 지정할 때 사용
- select문의 가장 마지막에 추가
산술연산자
select 5 + 3 as 덧셈, 20 - 3 as 뺄셈, 14 * 3 as 곱셈, 50 / 5 as 나눗셈;
-> 하나의 행으로 출력됨
논리연산자
select actor_id as aid, last_update as l_d
from actor
where not first_name = 'ED' or last_name = 'CHASE'
order by aid;
WHERE NOT : 특정 조건을 만족하지 않는 행을 선택
집합연산자
UNION : 집합 연산자 중에 합집합에 대한 연산자만 제
select actor_id, last_update
from actor
where last_update > '2006-02-15'
union
select actor_id, last_update
from actor
where first_name = 'ZERO' and last_name = 'CAGE'
order by actor_id;
'2006-02-15' 날짜도 WHERE 조건에 들어갈 수 있음
IN 연산자
SELECT * FROM sakila.finance_data
where Mutual_Funds in (1,2);
BETWEEN 연산자
SELECT * FROM sakila.finance_data
where age between 20 and 30;
LIKE 연산자
SELECT gender, age FROM sakila.finance_data
where gender like 'F%';
-> % , _ : 와일드카드 문자
( _ : 한글자 , % : 글자수 상관없)
Fixed_Deposits 이 5와 10사이인 성별과 나이를 조회
SELECT gender, age FROM sakila.finance_data
where Fixed_Deposits between 5 and 10;
SQL 함수
: SQL 함수는 SELECT 뒤에 바로 사용
단일행 함수의 종류
- 문자열 함수
CHAR_LENGTH(문자열) : 문자의 개수
LENGTH(문자열) : 문자열에 할당된 바이트 수
CONCAT('문자열1', '문자열2') : 문자열을 연결
CONCAT_WS('-(구분자)', '2024', '08', '25') : 구분자와 함께 문자열 연결
LEFT(문자열, 길이) : 문자열의 왼쪽부터 길이만큼 문자열 반환
SUBSTR(문자열, 시작위치, 길이) : 지정한 위치로부터 길이만큼의 문자열 반환
SUBSTRING_INDEX(문자열, 구분자, 인덱스) : 지정한 구분자를 기준으로 문자열을 분리해서 가져
LPAD(문자열, 길이, 변환할 문자열) : 지정한 길이에서 문자열을 제외한 빈칸을 특정 문자로 채울 때 사용
-> LPAD 는 왼쪽에 RPAD는 오른쪽에 특정 문자열을 채움
LTRIM() : 왼쪽의 공백을 제거할 떄 사용
RTRIM() : 오른쪽 공백을 제거할 때 사용
숫자형 함수
ceiling(), floor(), round(값, 자릿수), truncate(값, 자릿수)
USE sakila;
# ceiling 올림
select ceiling(age) as ceil_age
from finance_data;
# floor 버림
select floor(age) as floor_age
from finance_data;
# round 지정한 위치 반올림
select round(age, 2) as round_age
from finanace_data;
# truncate 지정한 위치 버림
select truncate(age, 2) as round_age
from finance_data;
데이터 사용 예시
# 데이터 사용
select ceiling(123.567),
floor(123.567), round(123.567),
round(123.567, 2), truncate(123.567, 2);
mod 연산
: %, 피연산자 mod 피연산
select mod(301, 4), 301 % 4, 301 mod 4;
age가 홀수인지 짝수인지 나머지값 연산으로 출력
select mod(age, 2) as mod_age from finance_data;
power()
: n제곱승을 값을 반환하는 함수 (거듭제곱)
select power(age, 2.5) as pow_age
from finance_data;
sqrt()
: 제곱근 값을 반환하는 함
select sqrt(age) as pow_age
from finance_data;
rand()
: 0과 1사이 임의이 실수값을 반환하는 함
select rand() as rand_value
from finance_data;
문제 예제
문제1 : age의 2.5제곱을 계산하고 소수점 둘째 자리까지 반올림하여 rounded_power_age로 출력하시오.
select round(power(age, 2.5), 2) as rud_pow_age
from finance_data;
문제2 : Mutual_Funds의 제곱근이 3 이상인 레코드만 조회하여 sqrt_mutual_funds로 출력하시오.
select sqrt(age) as sqrt_mutual_funds from finance_data
where sqrt(age) >= 3;
문제3 : Debentures의 네제곱을 계산한 후, 그 값의 제곱근을 구하여 sqrt_power_debentures로 출력하시오.
select sqrt(power(Debentures, 4)) as sqrt_power_debentures
from finance_data;
문제4 : 레코드를 임의의 순서로 정렬하여 random_order로 출력하시오.
select * from finance_data
order by RAND();
현재 날짜/ 시간 반환 함수
현재 날짜 / 시간 반환 함수
NOW() : 현재 서버 시간 확인
- NOW()는 쿼리가 실행될 때의 날짜와 시간을 반환
- 쿼리 실행 시간에 고정되어 있고, 동일 쿼리 내에서 여러 번 호출되더라도 동일한 값을 반환
select now() as now_time;
현재 날짜와 시간을 inv_now라는 별칭으로 표시
select Investment_Avenues, NOW() as inv_now
from finance_data;
SYSDATE()
- SYSDATE()는 함수가 호출될 때의 시스템 날짜와 시간을 반환
- 쿼리 실행 시간보다는 함수 호출 시의 정확한 시간을 반환하며,
- 동일 쿼리 내에서 여러 번 호출되면 서로 다른 값을 반환할 수 있음
select sysdate() as sysdate;
CURDATE() : 시스템의 현재 날짜를 반환
CURTIME() : 시스템의 현재 시간을 반환
select curdate() as curdate, curtime() as curtime;
date_format() :
날짜 및 시간 값을 지정된 형식으로 반환
- %Y: 4자리 연도 (예: 2024) %y: 2자리 연도 (예: 24)
%m: 2자리 월 (01-12) %c: 월 (1-12)
%d: 2자리 일 (01-31) %e: 일 (1-31)
%H: 2자리 시 (00-23, 24시간 형식) %h: 2자리 시 (01-12, 12시간 형식)
%i: 2자리 분 (00-59) %s: 2자리 초 (00-59) %p: AM 또는 PM
%a: 요일의 축약형 이름 (예: Sun, Mon) %W: 요일의 전체 이름 (예: Sunday, Monday)
select date_format(now(), '%Y-%m-%d %H-%i-%s') as col1;
연도, 분기, 월, 일, 시, 분, 초 반환 함수
YEAR(), QUARTER(), MONTH(), DAY(), HOUR(), MINUTE(), SECOND()
문제1 : last_update에서 연도를 추출하여 actor_id와 함께 출력
select YEAR(last_update) as '연도', actor_id from actor;
기간 반환 함수
DATEDIFF() : 기간을 일자 기준으로 반환
TIMESTAMPDIFF() : 기간을 지정한 단위 기준으로 보여줌
현재 날짜(NOW())와 last_update 열의 날짜 사이의 일수를 계산
select datediff(now(), last_update) as day_sin_upd from actor;
actor 테이블에서 현재 시간, 마지막 업데이트 시간, 그리고 현재 시간과 마지막 업데이트 시간 사이의 일수를 조회
select now() as time, last_update, datediff(now(), last_update) as day_sin_pid
from actor;
actor 테이블에서 각 레코드의 last_update 열과
현재 시간 (NOW()) 간의 차이를 개월 단위로 계산하여
mon_sin_up라는 열에 반환
select timestampdiff(MONTH, last_update, now()) as mon_sin_up from actor;
문제 예제
문제1: last_update와 현재 날짜 사이의 일 수가 30일 이상인 레코드만 조회하여 days_since_update로 반환하시오.
select datediff(now(), last_update) as days_since_update from actor
where datediff(now(), last_update) >= 30;
문제2:현재 시간과 last_update 사이의 달 수가 6개월 이상인 레코드만 조회하여
investment_duration_months로 반환하시오.
select timestampdiff(MONTH, last_update, now()) as mon_sin_up from actor
where timestampdiff(MONTH, last_update, now()) >=6;
-> TIMESTAMPDIFF 함수를 사용하여 달 수 차이를 계산
문제 3 : last_update와 현재 날짜 사이의 분 수를 계산하여 minutes_since_last_update으로 반환하시오.
select timestampdiff(MINUTE, last_update, NOW()) as minutes_since_last_update from actor;
ADDDATE() : 지정한 날짜를 기준으로 그 기간만큼 더한 날짜를 반환하는 함수
SUBDATE() :기간만큼 뺀 날짜를 반환함
select adddate(now(), -30), adddate(now(), interval 50 day);
select subdate(now(), interval 50 month);
문제1 : last_update에 30일을 더한 날짜가 현재 날짜보다 이전인 레코드만 조회하여 new_update_date로 반환하시오.
select adddate(last_update, interval 30 day) as new_update_date;
문제2 : last_update에 45일을 더한 날짜와
last_update에서 1년을 뺀 날짜를
각각 new_update_date와 earlier_update_date로 반환하고,
두 날짜를 'YYYY-MM-DD' 형식으로
formatted_new_update_date와 formatted_earlier_update_date로 출력하시오.
select
adddate(last_update, INTERVAL 45 DAY) as new_update_date,
subdate(last_update, INTERVAL 1 YEAR) as earlier_update_date,
date_format(adddate(last_update, INTERVAL 45 DAY), '%Y-%m-%d') as formatted_new_update_date,
date_format(subdate(last_update, INTERVAL 1 YEAR), '%Y-%m-%d') as formatted_earlier_update_date
FROM actor;
기타 날짜 반환 함수
last_day() : 해당 월의 마지막 일자 반환
dayofyear() : 현재 연도에서 며칠이 지났는지 반환
monthname() : 월을 영문으로 weekday()는 요일을 정수로
select last_day(now()), dayofyear(now()), monthname(now()), weekday(now());
해당 월의 마지막 날짜
문제 1 : last_update가 속한 주의 요일을 weekday_update로 반환하시오.
SELECT LAST_DAY(last_update) AS last_day_update,
DAYOFYEAR(last_update) AS day_of_year_update,
MONTHNAME(last_update) AS month_name_update
FROM actor;
문제 2. last_update의 달의 마지막 날이 해당 연도의 365일 중 300일 이후인 레코드만 조회하여 last_day_update와 day_of_year_update로 반환하시오.
SELECT LAST_DAY(last_update) AS last_day_update,
DAYOFYEAR(LAST_DAY(last_update)) AS day_of_year_update
FROM actor
WHERE DAYOFYEAR(LAST_DAY(last_update)) > 300;
문제 3. last_update가 속한 요일이 월요일(0)이면서 해당 달의 이름이 'January'인 레코드만 조회하여 weekday_evaluation과 month_name_evaluation로 반환하시오.
SELECT WEEKDAY(last_update) AS weekday_last_update,
MONTHNAME(last_update) AS month_name_last_update
FROM actor
WHERE WEEKDAY(last_update) = 0 AND MONTHNAME(last_update) = 'January';
문제 4. last_update의 달의 이름이 'March'이면서 해당 연도의 100일 이전인 레코드만 조회하여 month_name_equity_evaluation과 day_of_year_equity_evaluation로 반환하시오.
SELECT MONTHNAME(payment_date) AS month_name_equity_evaluation,
DAYOFYEAR(payment_date) AS day_of_year_equity_evaluation
FROM payment
WHERE MONTHNAME(payment_date) = 'August' AND DAYOFYEAR(payment_date) < 5000;
형 변환 함수
CAST() 함수
: 데이터 형식을 변환하는 데 사용되는 함수
주어진 값이나 열을 다른 데이터 타입으로 변환 가능
select cast(age as char) as age_as_string
from finance_data;
signed, unsigned
: 숫자 데이터 타입의 속성을 정의
- signed : 부호비트가 포함되어 있어서 부호가 있는 자료형
- unsigned : 부호비트가 없어서 부호가 없는 자료형이에요 그래서 양수만 표현 가능!
-> unsigned에서 더 큰 범위를 표현할 수 있다는게
signed의 부호비트를 unsigned는 다 숫자 표현하는데 쓰니까 수 표현 범위가 커지는 것
CONVERT() 함수
: MySQL에서 데이터 타입을 변환할 때 사용
예를 들어 숫자를 문자열로 변환하거나, 날짜를 다른 형식으로 변환하는 경우에 주로 사용
select convert(age, char) as age_as_string
from finance_data;
제어흐름함수
제어문
IF(조건, 수식1, 수식2)
select age, If(age >= 30, '30대 이상', '30대 미만') as col1
from finance_data;
문제1. age가 40 이상인 경우 'Very High', 30 이상 40 미만인 경우 'High',
그렇지 않으면 'Low'를 반환하여 funds_level로 출력하시오.
select If(age >= 40, 'Very High', IF(age >= 30, 'High', 'Low')) as funds_level
from finance_data;
문제2. payment_date가 2005년 이후인 경우 'Recent',
그렇지 않으면 'Old'를 반환하여 update_status로 출력하시오.
select payment_date, If(payment_date >= 2005, 'Recent', 'Old') as update_status
from payment;
IFNULL()
: 첫 번째 매개변수로 전달된 값이 NULL인 경우 두 번째 매개변수로 전달된 값을 반환
select ifnull(age, 0) as age_isnull from finance_data;
-> IFNULL(age, 0)은 age 컬럼의 값이 NULL이면 0을 반환하고, 그렇지 않으면 age 컬럼의 값을 그대로 반환
NULLIF()
: 첫 번째 매개변수와 두 번째 매개변수가 같으면 NULL을 반환하고, 다르면 첫 번째 매개변수 값을 반환
select nullif(age, 34) as age_isnull;
-> finance_data 테이블의 각 행에서 age 값이 34와 같으면 NULL을 출력하고,
그렇지 않으면 해당 age 값을 출력
문제1. age가 30인 경우 NULL을 반환하고, 각 레코드의 age 값을 2배로 하여 age_value로 출력하시오.
select 2 * nullif(age, 30) as age_value from finance_data;
문제2. last_update가 '2023-01-01'인 경우 NULL을 반환하여 update_date로 출력하시오.
select nullif(last_update, '2005-01-01') as update_date from actor;
CASE문
: 함수는 아니지만 조건 비교가 어러 개일 때 사용
select case when 조건 then 값
when 조건 then 값
else 값
end;
select age, case when age < 18 then '미성년자'
when age between 18 and 30 then '미성년자 아님'
else '시니어'
end as age_group
from finance_data;
집계함수
: 여러 행에 걸쳐 있는 값을 묶어서 계산을 수행하여 단일값을 반환하는 함수
GROUP BY절
각 age_group별로 총 gold를 계산하여 totalfund로 반환하시오.
select
case
when age < 18 then '미성년자'
when age between 18 and 30 then '청장년층'
else '중장년층'
end as age_group,
sum(gold) as total_gold
from finance_data
group by age_group;
문제1. 각 성별과 나이 그룹별 총 gold을 계산하고 10 이상인 그룹만 반환
select gender, age, sum(gold) as total_fund
from finance_data
group by gender, age
having sum(gold) >= 10;
문제2. 각 성별별 gold의 평균을 계산하고 10 이상인 그룹만 반환하여 avg_golds로 출력하시오.
select gender, avg(gold) as avg_golds
from finance_data
group by gender
having avg(gold) >= 6;
문제3. 각 성별과 나이 그룹별 총 gold을 계산하고 10 이상인 그룹만 반환
각 성별별 gold의 평균을 계산하고 6 이상인 그룹만 반환하여 avg_golds로 출력하시오.
select Dept_no, count(*) as 직원수
from employee
group by Dept_no
having count(*) >= 5;
문제4. 고객 주문 수와 고객의 주문 수가 10개 이상인 주문 조회
select customer_no, count(order_no) as 주문수
from orders
group by customer_no
having count(order_no) >= 10;
문제5. 제품별 총 판매 수량과 총 판매 수량이 100이상인 제품 조회
select product_no, sum(order_quantity) as '총판매수량'
from order_details
group by product_no
having sum(order_quantity) >= 100;
문제6. 각 도시별 고객 수와 고객 수가 10명 이상인 도시 조회
select city, count(customer_no) as 고객
from customer
group by city
having count(customer_no) >= 10;
문제7. 각 고객의 마일리지 합계와 마일리지가 10000이상인 고객 조회
select customer_no, sum(mileage) as 마일리지합계
from customer
group by customer_no
having sum(mileage) >= 10000;
WITH ROLLUP
: 부분과 전체 집합 같이 보고싶은 경우
문제1. 각 부서별 및 전체 직원 수 조회
select dept_no, count(*) as 직원수
from employee
group by dept_no with rollup;
문제2. 각 도시별 및 전체 고객수 조회
select city, count(*) as 고객수
from customer
group by city with rollup;
문제3. 각 제품별 및 전체 총 판매 수량과 총 판매 금액 조회
select product_no ,sum(order_quantity) as 총판매수량,
sum(order_quantity * unit_price * (1 - discount_rate)) as 총판매금액
from order_details
group by product_no with rollup;
복습 문제
문제 1. 각 직원별 및 전체 주문 처리 수와 평균 주문 처리 시간 조회 (order_detail 테이블)
select emp_no, count(order_no) as 전체주문처리수,
avg(request_date - order_date) as 평균주문처리시간
from orders
group by emp_no;
문제 2: 각 부서별 및 전체 직원 수와 평균 입사 날짜 조회(employee 테이블)
select Dept_no, count(emp_no) as 전체직원수,
avg(date_of_emp) as 평균입사날짜
from employee
group by Dept_no with rollup;
문제 3: 각 부서별 및 전체 직원 수와 평균 나이 조회 (employee 테이블)
select Dept_no, count(Emp_no) as 전체직원수, avg(year(now()) - year(birthday)) as 평균나이
from employee
group by Dept_no;
select ifnull(dept_no, '전체') as 부서번호,
count(emp_no) as 직원수,
avg(year(curdate()) - year(birthday)) as 평균나이
from employee
group by dept_no with rollup;
각 직원별 총 주문 수와 전체 총 주문 수 조회
(총 주문 수가 5개 이상인 직원만, 평균 처리 시간이 2일 이상인 경우 '지연'으로 표시)
select ifnull(product_no, '전체') as 제품번호,
sum(order_quantity) as 총판매수량,
case when avg(discount_rate) = 0 then '할인없음'
else avg(discount_rate)
end as 평균할인률,
sum(order_quantity * unit_price * (1 - discount_rate)) as 총판매금액
from order_details
where order_quantity > 0
group by product_no with rollup
having sum(order_quantity) >= 100 or product_no is null;
'파이썬 & 머신러닝과 딥러닝' 카테고리의 다른 글
데이터베이스 DDL, 뷰, 인덱스 (0) | 2024.07.10 |
---|---|
데이터베이스 CTE, 상관 서브쿼리, 다중 컬럼 서브쿼리, DML (0) | 2024.07.09 |
통계기반 데이터 분석 방법, 단순회귀분석, 종회귀모형, 모형의 선택, 모형의 타당성 (1) | 2024.07.03 |
통계의 종류, 히트맵, 람다함수, 이항분포, 베르누이분포, 기하분포 (1) | 2024.07.02 |
상관관계 확인, OpenAPI 사용, beautifulsoup, Selenium, 통계 분석 개념 및 정리 (0) | 2024.07.01 |