SQLD 시험 때문에 해커랭크를 잠시 미뤘다..
이것도 SQL 공부 아니냐며 합리화를 하면서 얼마 못 풀었다ㅠ
16.
해석) STATION 테이블에서 모음으로 시작하거나 끝나지 않도록 중복되지 않게 CITY를 가져와라.
REGEXP_LIKE(컬럼명, 정규식)
힌트)
표현 | |
^ | 문자열의 시작 부분과 일치. 매칭 파라미터의 m 옵션이 활성화되면 표현식을 사용하는 모든 행의 시작과 일치 |
$ | 문자열의 끝 부분과 일치. 매칭 파라미터의 m 옵션이 활성화되면 표현식을 사용하는 모든 행의 끝과 일치 |
* | 0개 이상 (zero or more) 일치 |
+ | 하나 이상 (one or more) 일치 |
? | 0 또는 1개 일치 (zero or one) |
. | NULL을 제외한 모든 문자와 일치 |
| | OR |
[ ] | [ ]에 있는 문자 중 하나를 일치시키려는 목록을 지정 |
[^ ] | [ ]에 있는 문자를 제외한 모든 문자를 일치시키려는 리스트 지정 |
( ) | 표현식을 하위 표현식으로 그룹화하는데 사용 |
{m} | m번 일치 |
{m,} | 적어도 m번 일치 |
{m,n} | 적어도 m번 일치 ~ n번 이하 일치 |
\n | () 번째 하위 표현식과 일치 |
[..] | 하나 이상의 문자가 될 수 있는 하나의 집합요소와 일치 |
[::] | 문자 클래스와 일치. [:digit:], [:punct:], [:alpha:] 등 |
[==] | equivalence 클래스와 일치 |
\d | 숫자와 일치 |
\D | 숫자가 아닌 것과 일치 |
\w | 영문자 숫자 밑줄문자(_) 와 일치 |
\W | 영문자 숫자 밑줄문자(_) 이외의 문자와 일치 |
\s | 공백문자와 일치 |
\S | 공백이 아닌 문자와 일치 |
\A | 문자열의 시작 부분과 일치, 혹은 새 행의 문자 앞에 있는 문자열의 끝 부분과 일치 |
\Z | 문자열의 끝과 일치 |
*? | 앞선 패턴이 0번 이상 발생 |
+? | 앞선 패턴이 한 번 이상 발생 |
?? | 앞선 패턴이 0 또는 1번 발생 |
{n}? | 앞선 패턴이 n번 일치 |
{n,}? | 앞선 패턴이 적어도 n번 일치 |
{n,m}? | 앞선 패턴이 적어도 n번 ~ m번 이하 일치 |
코드)
SELECT distinct CITY FROM STATION
WHERE REGEXP_LIKE(CITY, ' ^ [ ^ A E I O U ] | [ ^ A E I O U ] $ ' , ' i ');
정규식 해설 )
' 조건 | 조건 ' 형태로서 ' | ' 는 OR을 의미한다.
^ [ ] : 괄호 안에 있는 각 글자들로 시작하는 것들
[^ ] : 괄호 안에 있는 각 글자들을 제외
둘이 합쳐서 = 괄호 안에 있는 글자들로 시작하는 것들을 제외
[ ] $ : 괄호 안에 있는 글자들로 끝나는 것들
' i ' : 대소문자 구분을 안 하겠다는 뜻의 파라미터
17.
select DISTINCT CITY from STATION
where REGEXP_LIKE(CITY, '^[^AEIOU]', 'i')
and
REGEXP_LIKE(CITY, '[^AEIOU]$', 'i');
| 대신 쓸 수 있는 and 는... 기호를 모르겠어서 그냥 and 로 붙여주었는데
뭔가 많이 못생김...???
다른 사람들의 답변을 보니
'^[^AEIOU].*[^aeiou]$'
이게 적혀 있던데 .* 에 대한 건 찾아봐야겠다.
정규표현식
오라클 공식출처 : https://docs.oracle.com/cd/B13789_01/server.101/b10759/ap_posix001.htm#i690819
18.
해석 )
STUDENTS 테이블에서 75점이 넘는 학생들의 이름만 '끝의 세글자 기준'으로 오름차순 정렬해 들고오되,
겹치는 애들이 있다면 ID 번호로 정렬해라
코드 )
select Name From STUDENTS
where Marks > 75
order by substr(Name, -3), ID;
힌트 )
substr(문구, 자를길이)
substr(문구, 시작할위치, 자를길이)
19.
해석 ) 직원 이름을 알파벳 순서대로 불러와라
코드 )
select name from Employee
order by name;
이 문제는 왜 갑자기 나온거지...?
20.
해석)
월급 2000달러 초과이면서 10달 미만으로 다닌 직원 이름을 알파벳 순서대로 출력
코드)
select name from Employee
where salary > 2000 and months < 10
order by employee_id;
BASIC 문제는 끝!!!
21. 오라클로 소수 구하기
해석 ) 1000보다 작거나 같은 소수를 출력해라 (결과는 한줄로, '&'로 모두 조인시켜라)
코드)
with NUMBERS as ( select LEVEL NUM from dual where level >2 connect by level <= 1000)
select LISTAGG(N.NUM, '&') within group(order by N.NUM) from NUMBERS N
where not exists (select NUM from NUMBERS E where E.NUM < N.NUM and MOD(N.NUM, E.NUM)=0)
# 2~ 본인보다 작은 수를 나눴을때 나머지가 0이 아닌게 하나도 없는 것 = 소수
cf. CONNECT BY (계층적 쿼리)
- 반복문 FOR 문하고 비슷함 (상위계층부터, 하위계층까지 쭉 찾기를 반복)
select lpad(' ',(level-1)*2,' ')||직원 직원, 직급
from 직원
start with 직원 = '회장님'
connect by 직속상사 = prior 직원
- DUAL : 더미 테이블 >>> 함수(계산)을 실행할 때 임시로 사용 (특정 테이블을 생성할 필요가 없어짐)
- LEVEL : 오라클 모든 쿼리에서 사용 가능한, 단계를 나타내는 '가상' 열
- LPAD( ' ', (LEVEL-1) * 5 ) --> 1레벨(맨위계층)이면 좌측에 0공백 채우기 / 2레벨이면 좌측에 5공백, .....
- 쭈우욱 가상 데이터를 만들어놓고 중간중간 누락이 돼있는 것들을 보완해줄 수 있음 (ex.시계열데이터)
- SELECT LEVEL * 2 FROM DUAL CONNECT BY LEVEL < 100 ;
>>> 값을 2부터 2 씩 증가시켜서 100 미만까지 출력해라
LISTAGG 함수 기본 사용법
LISTAGG(컬럼명, '구분기호') WITHIN GROUP(ORDER BY 정렬 기준 컬럼)
EXISTS(서브 쿼리)는 서브 쿼리의 결과가 "한 건이라도 존재하면" TRUE 없으면 FALSE를 리턴
NOT EXISTS(서브 쿼리)는 서브 쿼리의 결과가 "없으면" TRUE , 있으면 FALSE를 리턴