내일 배움 캠프 사전캠프 TIL
3일 차에 느낀 개인적인 에세이
이놈의 고질병, 또 재발한 것 같다. 인생을 장거리 마라톤이라고 한다면 대학교 졸업 전까지는 옆에서 함께 뛰는 경쟁자들, 나의 속도를 맞춰주는 든든한 페이스메이커 등이 있었기 때문에 시간에 쫓기는 일이 없었다. 그러나 내 주변에 그 누구도 없는 지금, 왜 이렇게 마감 시간에 허덕이는 나로 변한 것인지 가끔씩 스스로도 놀랄 때가 있다. 오늘도 SQL 수강 전 마감 기한이 이틀 남은 타 기업에 지원할 자기소개서 에세이를 쓰느라 오전 내내 컴퓨터 앞에 앉아 시간을 보냈다. 물론 해당 기업의 지원은 여러 분야 중 어느 곳을 지원할지 고민하다가 시간이 지체된 이유가 있긴 했다. 다음 주 주말에 토익 시험을 봐야 하는데, 진짜 다음 주에 벼락치기로 토익공부를 하는 불쌍한 나의 모습을 보고 싶지 않다면 내일부터라도 토익공부를 시작해야 한다.
배운 점은? (SQL)
2일 차에 1주 차와 2주 차를 포함하여 성공적으로 강의를 수강한 기세를 이어받아 주저 없이 3주 차 SQL 수업을 수강하기 시작했다. 단순한 엑셀 계산에 사용되는 구문들이라 하더라도 주차가 늘어남을 거듭할수록 난이도는 지수승으로 증가하는 느낌이다. 오늘 그 상자를 함께 열어보도록 하자.
업무를 하며 필요한 문자 포맷이 다를 때 SQL로 가공할 수 있는 방법들로는 replace, substring, concat으로 총 3가지가 있다.
(1) 특정 문자를 다른 문자로 바꾸고 싶다면 replace를 쓴다. replace(바꿀 컬럼, 현재 값, 바꿀 값)으로 구문을 쓸 수 있는데, 이때 첫 번째 문자인 현재 값이 다른 문자로 바꿔줄 문자고, 두 번째 문자인 바꿀 값이 실제 결과로 나오는 바뀐 문자다.
Fig 1의 의미는 restaurant_name의 컬럼에서 모든 항목에 존재하는 blue라 적힌 부분을 모두 pink로 바꾸는 의미다. 현재 값과 바꿀 값만 replace () 안에 적는 것이 아닌, 바꿀 컬럼도 잊지 말고 적어줘야 한다.
(2) 전체 문자 중 원하는 문자만 남기고 싶다면 특정한 문자만 뽑아주는 구문인 substring을 쓴다. 구문으로 쓸 때는 substring을 써도 되지만 간단하게 표현하기 위해 substr로 쓴다. Fig 2를 먼저 본 후 설명을 이어가겠다.
Fig 2를 보면, 두 번째 줄에 substr(addr, 1, 2)라 쓰여있다. 여기서 addr은 replace처럼 컬럼을 지정해 준 것이고, 1은 어디에서부터 문자를 뽑아올지를 지정한 것으로, 첫 번째 문자부터 뽑아온다는 뜻이다. 2는 글자 수를 의미하며, addr 컬럼에서 데이터를 뽑아오는데, 첫 번째 문자(1)에서 두 글자씩 뽑는다는 의미다. 이를 합치면, 첫 번째 문자부터 두 글자만 뽑아서 컬럼 항목에 나타나게 된다. 예시로 항목에 '서울특별시'가 있었다면, 구문을 통해 얻은 데이터의 항목에는 '서울'만 남게 되는 것이다. 또한 항목에 '묵 돌'이 있었다면, 구문을 통해 얻은 데이터의 항목에는 '묵 '만 남게 된다. 공백도 글자 수에 포함되는 것을 주의하자(!!!)
Fig 2를 마저 보면, 서울특별시를 제외한 다른 모든 지역을 배제하기 위해 마지막 줄에 like + '% %'를 사용한 것이 보인다. 이를 통해 다른 항목은 제외하고 지역명에 서울만 나타나게 된다.
(3) 이후에 설명하는 것은 개인적으로 제일 어렵지 않나 생각하는 포맷 변환 방법이다. 원하는 데이터를 모두 붙여주는 함수로는 concat을 사용한다. 마찬가지로 fig 3을 먼저 본 후 설명을 이어가겠다.
세 번째 줄부터 차근차근 설명을 진행하겠다. concat ()의 괄호 안에 음식점 이름을 쓰고, 중간에 두 컬럼을 구분하기 위한 하이퍼 '-'을 사용한 후, 마지막에 음식 종류를 쓴 것이 보인다. 이처럼 구문을 쓰면 나오는 데이터는 각 컬럼의 항목들을 합친 데이터가 나오게 된다. 예시로 레스토랑이 아웃백, 음식 종류가 스테이크인 열이 각 항목에 존재한다면 fig 3의 데이터를 써서 아웃백-스테이크로 나타낼 수 있다. 세 번째 줄을 보면, 앞서 설명한 substr이 concat 안에 추가로 들어간 것을 볼 수 있다. 만약 아웃백, 스테이크, 서울특별시라면 concat을 활용하여 생성된 데이터의 항목은 '서울 아웃백'이 된다. 추가로 세 번째 줄에 괄호가 아닌 대괄호를 표시해 놨는데, 괄호를 써도 데이터가 나오는지는 확인을 해본 후 4일 차에 작성하도록 하겠다.
concat 안에는 컬럼, 한글, 영어, 숫자, 기타 특수문자를 모두 붙일 수 있으며, 기본적으로 문자를 붙이므로 작은따옴표를 붙인다.
(4) 실습 과정에서 2일 차에 배운 group by 구문을 사용하였는데, select 옆에 컬럼을 그대로 복사 붙여 넣기 하여 작성한 것이 아닌 숫자 1, 2로 group by 구문의 첫 번째 줄과 두 번째 줄을 표기하더라도 데이터는 똑같이 나타난다. 만약 긴 구문이라면 숫자로 적는 행위가 시간 단축은 되지만 헷갈릴 수 있으므로 그냥 select 옆의 구문으로 적는 것이 좋아 보인다.
Fig 5는 시간 날 때 집중적으로 확인하도록 하자. 많은 양의 컬럼들이 모인다면 정말 많은 구문들이 필요하겠다는 생각을 하게 되었다.
조건에 따라 포맷을 다르게 변경할 수도 있으며, if, case 절을 사용하여 진행한다.
(1) 예시를 먼저 들어보겠다. 음식 종류가 korean이면 '한식', korean이 아닌 경우에는 '기타'라고 지정하거나, 음식 단가를 주문 수량이 1일 때는 음식 가격, 주문 수량이 2개 이상일 때는 음식가격/주문수량으로 지정하는 것이 가능하다. 이처럼 원하는 조건만 뽑아내고, 원하지 않는 조건들은 기타라고 지정하기 위해 if 절이 사용된다. if를 구문으로 사용할 때는 if(조건, 조건을 충족할 때, 조건을 충족하지 않을 때)로 쓴다.
앞서 말한 if의 사용법에 따라 '조건'에는 평택군이 들어가는 주소가 뽑힐 것이고, 평택군이 들어가는 조건 중 문곡리가 들어간다면 문가리로 변환을 시키고, 평택군이 들어가지 않는다면 그냥 주소로 쓰게끔 명령을 내렸다. 또한 맨 밑의 줄을 보면 문곡리가 들어가는 주소만 원하기 때문에 결국 얻어지는 데이터는 문곡리가 들어가는 데이터들 중 평택군을 포함하는 주소들만 문곡리에서 문가리로 변환된 주소로 데이터가 나타날 것이다.
앞선 fig 6은 if 구문 내에 replace가 들어간 것이라면, 반대로 fig 7은 substr 안에 if절과 replace가 들어간 복잡한 경우다. 이메일 중 gmail을 포함하고 있을 때는 메일 주소를 그냥 쓰지 않고 gmail을 @gmail로 바꾸고, gmail이 아닌 다른 이메일 도메인은 그대로 이메일을 쓰라는 의미다. 만약 substr을 쓰는 과정에서 어디에서 문자를 뽑아올지만 중요하고, 뒤에 해당하는 글자 수는 중요하지 않다면 fig 7처럼 안전하게 뒤에 해당하는 글자수에 큰 숫자를 쓰거나 아니면 숫자를 안 쓰고 괄호를 닫아도 상관없다.
if절 안에 like, replace와 같이 사용하는 여러 가지 구문을 결합할 수 있다는 것을 염두하면 좋다.
(2) 앞서 설명한 if 절의 경우 한 가지 조건에 대해서만 분류가 가능하기 때문에 한계점이 존재한다. 그러나 case의 경우 if처럼 쓸 수 있을 뿐만 아니라 여러 개의 조건을 분류할 수 있다는 특징이 있다. 예시로 korean은 한식, japanese와 chinese는 아시아, 나머지 국가들은 기타로 분류하고 싶다면 case를 쓰면 된다. case의 사용 방법은 각 조건을 줄 때 when을 쓰며, when에 속할 때 줄 수 있는 값을 then을 주고, 조건에 부합하지 않는 case는 esle를 쓰고, 끝낼 때는 end를 쓴다. Fig 8은 앞서 설명한 각 나라에 대한 음식 종류 카테고리를 여러 개로 만들어 생성한 명령어다.
즉 case 절을 사용하면 여러 개의 새로운 카테고리를 만들 수 있고, 연산식을 적용할 조건을 지정할 수 있다(fig 9 참고).
Fig 9는 음식 단가에 대해 주문 수량이 1일 때는 음식 가격, 주문 수량이 2개 이상일 때는 음식가격/주문수량 (=음식가격 나누기 주문수량)으로 지정한 것이다.
추가적인 실습을 살펴보도록 하겠다.
(1) 10세 이상, 30세 미만 고객의 나이와 성별로 그룹을 나누고, 이름도 함께 출력한다면?
1~4번째 줄의 between 구문에 괄호를 적은 이유는 각 줄에서 and가 너무 많아 헷갈리는 것을 방지하기 위해서 적은 것이며, 있어도 없어도 출력되는 데이터는 동일하다. 또한 30대 이상의 사람들은 else 조건을 추가로 적지 않았기 때문에 데이터에 나타나지 않게 된다.
(2) 지역과 배달시간을 기반으로 배달수수료를 구해보되, 식당 이름과 주문 번호를 함께 출력해 보자. 지역은 서울과 기타로 분류하며, 서울은 시간 계산 * 1.1, 기타는 곱하는 값이 없다. 또한 배달 시간은 25분까지 괜찮으며, 25분을 초과하여 30분까지는 음식 가격의 5%, 30분을 초과하면 음식 가격의 10%를 부과하도록 하자.
명령어의 두 번째 줄을 보면 25분 초과 30분 미만으로 해야 하는 것이 맞지 않는가 반문할 수 있다. 그러나 두 번째 줄에서 25분 초과만 적은 이유는 첫 번째 줄에서 30분이 초과된 case가 이미 모두 걸려졌기 때문이다. 엄밀이 하고 싶다면 >25가 아닌 between 26 and 30이라 조건을 적어도 상관없다. 또한 1,2 번째 줄을 보면 case 절 안에 * if 절이 들어가더라도 데이터를 구하는데 문제없는 것을 볼 수 있다.(!!!)
(3) 주문 시기와 음식 수를 기반으로 배달할증료를 구해보자. 주문 시기 중 평일은 기본료 3000원을 받고, 주말은 기본료 3500원을 붙는다. 또한 음식 수가 3개 이하면 할증이 없고, 3개 초과면 기본료에 1.2를 곱한 값을 받는다.
(4) 배달시간이 늦었는지 판단하는 데이터를 구해보자. 주문 시기 중 평일은 25분 이상, 주말은 30분 이상 소요된다.
마치며
SQL에 사용되는 많은 포맷 구문들을 추가로 배웠다. 막상 배울 때는 이해가 된다고 생각할지라도 그것들을 모두 활용하여 응용할 줄 아는 실력이 진정한 실력이라 생각한다. 주차가 바뀔수록 어려워지는 난이도에 대비하기 위해 열심히 회독을 진행해야겠다.