모든 곳에서 사용이 가능
자바의 if/switch와 비슷한 행동
문장 단위의 제어(X) -> 값을 제어(O)
조건을 만족하지 못하는 컬럼은 null을 반환(★★★★★)
-- 이름과 성별 가져오기
select
last || first as name,
gender
from tblComedian;
-- m은 남자,f는 여자로
-- 원본테이블을 가져와서 가공한 가상의 컬럼
-- case end -> 자바의 {} 블럭 역할
select
last || first as name,
case
when gender = 'm' then '남자' -- 'm'이라면 '남자'를 반환
when gender = 'f' then '여자' -- 'f'라면 '여자'를 반환
end as gender
from tblComedian;
select
name,
case
when continent = 'AS' then '아시아'
when continent = 'EU' then '유럽'
when continent = 'AF' then '아프리카'
-- when continent = 'AU' then '오세아니아'
-- when continent = 'SA' then '남아메리카'
-- else '기타' -- 앞의 세조건을 만족 못하는 나머지는 '기타'로 반환
-- when continent = 'AU' then continent -- 조건의 반환값이 반드시 상수일 필요가 없다.(자신의 컬럼값을 돌려주는 것도 가능)
-- else continent -- 나머지는 원래의 값으로 리턴한다.
-- else capital -- 의미는 다른 항목들과 동일해야한다.
else population -- 자료형이 다른 항목들과 동일
else '기타'
end as continent
from tblCountry;
select
last || first as name,
weight,
case
when weight > 100 then '과체중'
when weight > 50 then '정상체중'
when weight > 0 then '저체중'
end as state,
case
when weight between 50 and 100 then '정상체중'
else '비정상체중'
end as state2
from tblComedian;
select
title,
case
when completedate is null then '완료'
when completedate is not null then '미완료'
end as state
from tblTodo;
select
name,
jikwi,
case
when jikwi in ('과장', '부장') then '세단'
when jikwi in ('대리', '사원') then '경차'
end as car
from tblInsa;
select
name,
buseo,
jikwi,
-- 3년 미만: 주니어
-- 3년 ~ 7년 미만 : 시니어
-- 7년 이상 : 익스퍼트
case
when ibsadate > '2018-05-14' then '주니어'
when ibsadate <= '2018-05-14' and ibsadate > '2014-05-14' then '시니어'
when ibsadate <= '2014-05-14' then '익스퍼트'
end as state
from tblInsa;
-- 여자친구 유무
select
name,
case
when couple is null then '없음'
when couple is not null then '있음'
end as state
from tblMen;
-- [문제]
-- tblInsa. sudang
-- 결과셋 : name, buseo, jikwi, sudang, 추가수당(계산)
-- 정책1 : 직위별 수당 + a > 부장(X2), 과장(X1.7), 대리(X1.5), 사원(X1.3)
-- 정책2 : 직위별 수당 + a > 부장, 과장(X2), 대리, 사원(X1.5)
[WITH ]
SELECT column_list
FROM table_name
[WHERE search_condition][GROUP BY group_by_expression]
[HAVING serach_condition]ORDER BY order_expression [ASC|DESC]];
SELECT column_list
FROM table_name
[WHERE search_condition]ORDER BY order_expression [ASC|DESC]];
SELECT 컬럼리스트
FROM 테이블명
WHERE 조건
ORDER BY 정렬기준;
select를 구성하는 모든 절들은 실행 순서가 있다. (불변) -> 무조건 암기(이해)★★★★★
-- 체중 오름차순으로 정렬
select
last || first as name,
weight
from tblComedian
-- order by weight asc; -- 체중을 기준으로 정렬, 정렬 순서 지정을 안하면 오름차순 (asc 생략가능(ascending 오름차순))
order by weight desc; -- descending 내림차순
-- order by 대상 컬럼이 결과셋에 포함되지 않아도 상관없다. -> 보편적으로는 포함시킨다.
select
last || first as name -- weight X -> 없으면 무슨 기준으로 정렬되는지 알 기 어려움.
from tblComedian
order by weight desc;
select -- 3. 원하는 컬럼만 선별
last || first as name,
weight,
gender
from tblComedian -- 1. 테이블 지정 (전체데이터)
where gender = 'm' -- 2. 원하는 레코드만 선별 : f(여자) 탈락
order by weight desc; -- 4. 결과셋의 정렬
-- 다중 정렬(정렬의 차원 높이기.)
select
name, buseo, jikwi, city
from tblInsa
-- order by buseo asc; -- 1차 정렬 (기준 1개)
-- order by buseo asc, jikwi asc; -- 2차 정렬(기준 2개)
order by buseo asc, jikwi asc, city asc; -- 3차 정렬 (기준 3개)
-- order by 2 asc, by 3 asc, by 4 asc; -- 첨자로 컬럼을 지정 -> 사용금지!!!!
-- 수당 + 기본급(계산된 값)의 내림차순으로 정렬
select
name, basicpay, sudang, basicpay + sudang
from tblInsa
order by basicpay + sudang desc; -- ★★★★
-- 직위별 수당 + a > 부장, 과장(X2), 대리, 사원(X1.5)
select
name, sudang, jikwi,
case
when jikwi in ('부장', '과장') then sudang * 2
when jikwi in ('사원', '대리') then sudang * 1.5
end as sudang2 -- as 생략가능(그래도 쓰는 걸 권장)
from tblinsa
-- order by sudang2 desc; 아래와 같은 구문
order by case
when jikwi in ('부장', '과장') then sudang * 2
when jikwi in ('사원', '대리') then sudang * 1.5
end desc;
/*
컬럼이기때문에 컬럼이 오는 자리에 올 수 있음!!!
case
when jikwi in ('부장', '과장') then sudang * 2
when jikwi in ('사원', '대리') then sudang * 1.5
end
*/
-- 팁!!(★★★★)
-- 직위를 정렬(부장,과장,대리,사원) -> 가나다순(x) -> 직위순으로!!
select
name, buseo, jikwi
from tblInsa
order by jikwi desc;
select
name, buseo, jikwi
-- case
-- when jikwi = '부장' then 1
-- when jikwi = '과장' then 2
-- when jikwi = '대리' then 3
-- when jikwi = '사원' then 4
-- end as no
from tblInsa
-- order bu no asc; -> 사용가능 -> 결과에 123가 결과테이블에 나타난다... -> Alias 사용불가..
order by case
when jikwi = '부장' then 1
when jikwi = '과장' then 2
when jikwi = '대리' then 3
when jikwi = '사원' then 4
end asc;
select name from tblCountry;
select count(name) from tblCountry; -- 14 (레코드 수)
select count(name) -- 3. 33개
from tblinsa -- 1. 60개
where city in ('서울', '경기'); -- 2. 33개
select area from tblCountry;
select count(area) from tblCountry;
select population from tblCountry;
select count (population) from tblCountry; -- 13 -> null이 들어있는 항목은 안센다.
-- ORA-00937: not a single-group group function
-- 컬럼리스트에 집계함수와 단일 컬럼은 동시에 사용할 수 없다. ★★★★★
-- 에러 : 집합정보, 개인정보는 성질이 다르기 때문에 같은 테이블을 사용할 수 없다. (무결성이 깨진다.)
select count(name), name from tblcountry;
-- 따로 확인해야한다.
select count(name) from tblcountry;
select name from tblcountry;
-- 집합 정보끼리는 동시에 사용 가능
select count(name), count(area) from tblcountry;
-- 매개변수의 컬럼은 하나만 가능
-- 에러 : ORA-00909: invalid number of arguments
select count(name, area) from tblcountry;
-- 살짝 고민? - ()안에 어떵 컬럼을 집어 넣지?
-- tblCountry의 나라 개수?
select count(name) from tblcountry; -- 14
select count(capital) from tblcountry; -- 14
select count(area) from tblcountry; -- 14
select count(population) from tblcountry; -- 13 (null은 제외..)
select count(*) from tblcountry; -- 14 -> 무조건 모든 레코드 개수가 반환된다.(행을 센다. - 행에 하나의 데이터만 있어도 레코드(행)전체를 보기 때문에 데이터가 있다고 생각한다.) ★★★★★
select * from tblcountry;
select * from tbltodo;
-- 아직 안한 일의 갯수 8개
select count(*) from tbltodo where completedate is null;
-- 한 일의 갯수? 12개
select count(*) from tbltodo where completedate is not null;
-- 안한 일의 갯수, 한 일의 갯수 -> 하나의 결과셋으로
select
count(*) as "전체 할 일 갯수",
count(completedate) as "한 일의 갯수",
count(*) - count(completedate) as "아직 안한 일의 갯수"
from tbltodo;
-- 연락처가 없는 직원 수
select
count(*) as "총 직원수", -- 60
count(tel) as "연락처가 있는 직원수", -- 57
count(*) - count(tel) as "연락처가 없는 직원수" -- 3
from tblInsa;
-- tblInsa -> buseo컬럼 -> 어떤 부서들이 있나요?
-- tblInsa -> buseo컬럼 -> 부서가 몇개 인가요? -> 숫자세기 (중복제거)
select count (distinct buseo) from tblInsa;
-- tblComedian 남자 몇명? 여자 몇명?
select * from tblcomedian;
select count(*) from tblcomedian where gender= 'm';
select count(*) from tblcomedian where gender= 'f';
-- 전체인원수, 남자인원수, 여자인원수 -> 결과셋
-- 힌트 : count() + case end + null 존재
select
count(*) as "전체 인원수",
count(case
when gender = 'm' then 1 -- null빼고 다세기
end) as "남자 인원수",
count (case
when gender = 'f' then 1 -- null빼고 다세기
end) as "여자 인원수"
from tblcomedian;
select avg(basicpay) from tblInsa; -- 1556526.666...
-- 평균 급여보다 많이 받는 직원들 명단을 가져오시오.
select * from tblInsa where basicpay > 1556526; -- 27
-- 에러 : ORA-00934: group function is not allowed here ★★★★★
-- 개인데이터와 집합데이터는 동시에 사용할 수 없다.
-- where절에는 집계함수를 사용할 수 없다. > where절은 개인에 대한 조건절(집합 정보를 가져올 수 없다.)★★★★★
select * from tblInsa where basicpay > avg(basicpay); -- 27
-- tblCountry.
-- 아시아(AS)와 유럽(EU)에 속한 나라의 개수?? -> 7개
select count(*) from tblCountry where continent in ('AS', 'EU');
-- 인구수가 7000 ~ 20000 사이인 나라의 개수?? -> 2개
select count(*) from tblCountry where population between 7000 and 20000;
-- hr.employees
-- job_id > 'IT_PROG' 중에서 급여가 5000불이 넘는 직원이 몇명? -> 2명
select count(*) from hr.employees where job_id = 'IT_PROG' and salary >= 5000;
-- tblInsa
-- tel. 010을 안쓰는 사람은 몇명?(연락처가 없는 사람은 제외) -> 42명
select count(*) from tblinsa where not tel like '010%' and tel is not null;
-- city. 서울, 경기, 인천 -> 그 외의 지역 인원수? -> 18명
select count(*) from tblinsa where city not in ('서울', '경기', '인천');
-- 80년대생 + 여자 직원 총 몇명? -> 9명
select count(*) from tblinsa where ssn like '8%-2%';
select weight from tblcomedian; -- 몸무게 총합
select sum(weight) from tblcomedian;
select sum(first) from tblcomedian; -- 문자열은 합할 수 없음 에러 : ORA-01722: invalid number
select
sum(basicpay), sum(sudang),
sum(basicpay) + sum(sudang),
sum(basicpay + sudang)
from tblInsa;
-- 60명 전원의 급여
select
basicpay
from tblinsa;
-- 직원들의 모든 급여의 합
select
sum(basicpay)
from tblinsa;
select
sum(basicpay), count(*),
sum(basicpay) / count(*), -- 평균
avg(basicpay) -- 평균
from tblinsa;
-- 평균인구수? 14475.14.., 15588
select
sum(population) / count(*),
sum(population) / count(population), -- 케냐 인구수 null -> 13
avg(population), -- null은 취급 x ★★★★★★★★★★
count(*), -- 14
count(population) -- 13
from tblcountry;
-- 회사 성과급 지급
-- : 10명 팀원 -> 7명 참여 프로젝트 수익 발생, 3명 관련 없음
-- 1. 균등 지급 -> 수익 / 모든 팀원수 = sum() / count(*)
-- 2. 차등 지급 -> 수익 / 참여 팀원수 = sum() / count(참여팀원) = avg()★★★★★★★
-- 가장 높은 급여, 적은 급여
select max(basicpay), min(basicpay) from tblInsa;
-- 가나다순중 가장 먼저, 가장 마지막
select max(name), min(name) from tblInsa;
-- 입사날짜 가장 최근, 가장 오래된
select max(ibsadate), min(ibsadate) from tblInsa;
-- 1. 유럽과 아프리카에 속한 나라의 인구 수 합? tblCountry
select sum(population)
from tblcountry
where continent in ('EU', 'AF');
-- 2. 매니저(108)이 관리하고 있는 직원들의 급여 총합? hr.employees
select sum(salary) from hr.employees
where manager_id = 108;
-- 3. 직업(ST_CLERK, SH_CLERK)을 가지는 직원들의 급여 합? hr.employees
select sum(salary) from hr.employees
where job_id in ('ST_CLERK', 'SH_CLERK');
-- 4. 서울에 있는 직원들의 급여 합(급여 + 수당)? tblInsa
select sum(basicpay + sudang) from tblinsa
where city = '서울';
-- 5. 장급(부장+과장)들의 급여 합? tblInsa
select sum(basicpay) from tblinsa
where jikwi in ('부장', '과장');
-- 1. 아시아에 속한 국가의 평균 인구수? tblCountry
select avg(population) from tblcountry
where continent = 'AS';
-- 2. 이름(first_name)에 'AN'이 포함된 직원들의 평균 급여?(대소문자 구분없이) hr.employees
select avg(salary) from hr.employees
where first_name like '%AN%' or first_name like '%An%' or first_name like '%aN%' or first_name like '%an%';
-- 3. 장급(부장+과장)의 평균 급여? tblInsa
select avg(basicpay) from tblinsa
where jikwi in ('부장', '과장');
-- 4. 사원급(대리+사원)의 평균 급여? tblInsa
select avg(basicpay) from tblinsa
where jikwi in ('대리', '사원');
-- 5. 장급(부장,과장)의 평균 급여와 사원급(대리,사원)의 평균 급여의 차액? tblInsa
select
avg(case
when jikwi in ('부장', '과장') then basicpay
end)
-
avg(case
when jikwi in ('대리', '사원') then basicpay
end)
from tblinsa
-- 1. 면적이 가장 넓은 나라의 면적은? tblCountry
select max(area) from tblcountry;
-- 2. 급여(급여+수당)가 가장 적은 직원은 총 얼마를 받고 있는가? tblInsa
select min(basicpay + sudang) from tblinsa;
select height, weight, height / weight, round(height / weight) from tblComedian;
select 10 / 3 from tblComedian; -- 3.33333... -> 10개
select 10 / 3 from tblInsa; -- 3.33333.... -> 60개
select 10 / 3 from tblInsa where name = '홍길동';
select * from dual; -- 시스템 테이블★★★★ -> 특정테이블에 종속된 값이 아닌 값을 확인할 때 사용
select 10 / 3 from dual;
select round(987.654), round(987.654, 1), round(987.654, 2) from dual;
select round(avg(basicpay)) from tblInsa;
select round(name) from tblInsa; -- 에러
select round(ibsadate), ibsadate from tblInsa;
select
to_char(round(sysdate), 'yyyy-mm-dd hh24:mi:ss'),
to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss')
from tblInsa;
select
sysdate, -- 현재 시각
to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss')
from dual;
select
5.6789,
round(5.6789), -- 6
floor(5.6789), -- 5
trunc(5.6789), -- 5
trunc(5.6789, 1) -- 5.6
from dual;
select
3.1, -- 3.1
round(3.1), -- 3
ceil(3.1), -- 4
ceil(3.000000000000000000001), -- 4
floor(3.999999999999999999999) -- 3
from dual;
select mod(10, 3) from dual; -- 1
-- 100분 -> 1시간 40분
-- 100 / 60 -> 몫(시간)
-- 100 % 60 -> 나머지(분)
select
floor(100 / 60) as 시,
mod(100, 60) as 분
from dual;
select
abs(-10), abs(10),
power(2, 8),
sqrt(4)
from dual;
select
first_name,
upper(first_name),
lower(first_name)
from employees;
select initcap('abc') from dual; -- Abc 첫 글자만 대문자로
-- 이름에 'an'이 포함 검색(대소문자 상관없이)
select first_name from employees
where first_name like '%AN%' or first_name like '%an%'
or first_name like '%An%' or first_name like '%aN%';
select first_name from employees
where upper(first_name) like '%AN%';
select
'가나다라마바사아자차카타파하',
substr('가나다라마바사아자차카타파하', 5, 3), -- 마바사
substr('가나다라마바사아자차카타파하', 5) -- 마바사아자차타파하
from dual;
-- 주민등록번호 (1 : 남자 2 : 여자)
select count(*) from tblInsa where ssn like '%-1%';
select count(*) from tblInsa where substr(ssn, 8, 1) = '1';
select count(*) from tblInsa where substr(ssn, 8, 1) = '2';
select count(*) from tblInsa where substr(ssn, 8, 1) = '1' or substr(ssn, 8, 1) = '3';
select count(*) from tblInsa where substr(ssn, 8, 1) in ('2', '4');
select
name, ssn,
case
when substr(ssn, 8, 1) = '1' or substr(ssn, 8, 1) = '3' then '남자'
when substr(ssn, 8, 1) in ('2', '4') then '여자'
end as gender
from tblInsa;
select
name, '19' || substr(ssn, 1, 2) as birthyear
from tblInsa;
-- 장급(부장, 과장)들은 어떤 성을 가지고 있는지?
select
distinct substr(name, 1, 1)
from tblInsa
where jikwi in ('부장', '과장')
order by substr(name, 1, 1);
-- 직원 성? 26가지
select
distinct substr(name, 1, 1)
from tblInsa;
-- 각각의 성이 몇 명인지?
select
count(case
when substr(name, 1, 1) = '김' then 1
end) as "김",
count(case
when substr(name, 1, 1) = '이' then 1
end) as "이",
count(case
when substr(name, 1, 1) = '박' then 1
end) as "박",
count(case
when substr(name, 1, 1) = '정' then 1
end) as "정",
count(case
when substr(name, 1, 1) = '최' then 1
end) as "최",
count(case
when substr(name, 1, 1) not in ('김','이','박','정','최') then 1
end) as "기타"
from tblInsa;
-- 태어난 월별 순으로 정렬(ssn -> substr(ssn, 3, 2))
select
*
from tblInsa
order by substr(ssn, 3, 2) asc;
-- 컬럼 리스트에서 사용
select name, length(name) from tblCountry;
-- 조건절에서 사용
select name from tblCountry where length(name) > 3;
select name from tblCountry where length(name) between 4 and 6;
select name, capital from tblCountry where length(name) > length(capital);
-- 정렬에서 사용
select name, length(name) from tblCountry order by length(name) desc, name asc;
-- 제목이 길면 자르고 ...하기
select
case
when length(title) >= 8 then substr(title, 1, 8) || '..'
else title
end as title
from tblTodo;
-- hr.employees
-- 1. 전체 이름(first_name + last_name : fullname)이 가장 긴-> 짧은 사람 순으로 가져오기
-- 컬럼리스트 : first_name + last_name, length(fullename)
select
first_name || ' ' || last_name as fullname,
length(first_name || ' ' || last_name) as length
from employees
order by length(first_name || ' ' || last_name) desc;
-- 2. 전체 이름(first_name + last_name : fullname)이 가장 긴 사람이 몇글자? 가장 짧은 사람이 몇글자?
-- 컬럼리스트 : 숫자만 출력
select
max(length(first_name || ' ' || last_name)) as max,
min(length(first_name || ' ' || last_name)) as min
from employees;
-- 3. last_name이 4자인 사람들의 first_name이 궁금하다. 정렬 : first_name 길이 오름차순으로
select
first_name, last_name
from employees
where length(last_name) = 4
order by length(first_name) asc;
select
'안녕하세요. 홍길동님' as c1,
instr('안녕하세요. 홍길동님', '홍길동') as c2, -- 8
instr('안녕하세요. 홍길동님', '아무개') as c3, -- 0
instr('안녕하세요. 홍길동님. 잘가세요. 홍길동님', '홍길동', 11) as c4, -- 20
instr('안녕하세요. 홍길동님. 잘가세요. 홍길동님', '홍길동', instr('안녕하세요. 홍길동님', '홍길동')) as c5 -- 8 -- number instr(컬럼명, 검색어, 시작위치)
from dual;
-- 제목입니다. -> (*)제목입니다.
select
case
when instr(title, '자바') > 0 then '(*)' || title
else title
end as title
from tblTodo;
select
'1',
lpad('1', 3, '0'), -- ★
lpad('1', 3, '@'),
lpad(' ', 20, '='),
rpad('1', 3, '0'),
rpad('1', 3, '+')
from dual;
select
' 하나 둘 셋 ',
trim(' 하나 둘 셋 '),
ltrim(' 하나 둘 셋 '),
rtrim(' 하나 둘 셋 ')
from dual;
select replace('홍길동', '홍', '김'), replace('홍길동', '이', '김') from dual;
-- tblInsa, 직원명, 주민번호, 성별(남자,여자)
select name, ssn, substr(ssn, 8, 1) from tblInsa;
select name, ssn,
case
when substr(ssn, 8,1) = '1' then '남자'
when substr(ssn, 8,1) = '2' then '여자'
end
from tblInsa;
select name, ssn, replace(replace(substr(ssn, 8, 1),'1','남자'), '2', '여자') from tblInsa;
select
name,
case
when continent = 'AS' then '아시아'
when continent = 'EU' then '유럽'
when continent = 'AF' then '아프리카'
when continent = 'AU' then '오세아니아'
when continent = 'SA' then '아메리카'
end as continent,
replace(replace(replace(replace(replace(continent, 'AS', '아시아'), 'SA', '아메리카'), 'EU', '유럽'),'AF', '아프리카'), 'AU', '오세아니아')
from tblcountry;
select
name,
ssn,
decode(substr(ssn, 8, 1),'1', '남자', '2', '여자'), -- 못찾으면 null 반환
replace(replace(substr(ssn, 8, 1),'1','남자'), '2', '여자')
from tblInsa;
select
name,
continent,
decode(continent,'AS', '아시아', 'EU','유럽', 'AF', '아프리카', 'AU', '호주', 'SA', '아메리카')
from tblcountry;
-- 팁(★)
-- decode를 유용하게 써먹는 경우
select * from tblcomedian;
select count(*) from tblcomedian where gender= 'm';
select count(*) from tblcomedian where gender= 'f';
select
count(case
when gender = 'm' then '남자'
end),
count(case
when gender = 'f' then '남자'
end)
from tblComedian;
select
-- case
-- when gender = 'm' then 1
-- end,
count(decode(gender, 'm', 1)),
count(decode(gender, 'f', 1))
from tblComedian;
-- tblinsa. 부장 몇명?, 과장 몇명?, 대리 몇명?, 사원 몇명?
select
count(decode(jikwi, '부장', 1)) as 부장,
count(decode(jikwi, '과장', 1)) as 과장,
count(decode(jikwi, '대리', 1)) as 대리,
count(decode(jikwi, '사원', 1)) as 사원
from tblInsa;
-- tblAddressBook. job. 학생 몇명?, 건물주 몇명?
select
count(decode(job, '학생', 1)) as 학생,
count(decode(job, '건물주', 1)) as 건물주
from tblAddressBook;
-- tblAddressBook. address. 강동구 몇명? 마포구 몇명?
select
decode(address, '강동구', 123),
replace(address, '강동구', 123)
from tblAddressBook;
select
count(case
when instr(address, '강동구') > 0 then 1
end) as 강동구,
count(case
when instr(address, '마포구') > 0 then 1
end) as 마포구
from tblAddressBook;
select
count(*) - count(decode(instr(address, '강동구'), 0, 1)) as "강동구",
count(*) - count(decode(instr(address, '마포구'), 0, 1)) as "마포구"
from tblAddressBook;