D - 41 데이터베이스 그룹함수, JOIN, ANSI JOIN 자바스크립트 const키워드와 let키워드, 생성자함수에 의한 객체생성
데이터베이스
어제 배웠던 DECODE함수는 실제로는 많이 사용되지 않는다.
그 상위호환인 CASE문을 자주 사용하게 될 텐데, 이는 자바에서의 IF문과 비슷하다.
CASE와 END로 크게 구성되어있고 CASE문 안에 WHEN에 조건, THEN에 해당 조건을 만족했을 때 수행할 내용을 명시한다.
어제는 DECODE로 했던 것을 CASE문으로 하면 훨씬 가독성이 좋아진다는 것을 알수 있다.
여기서 TO_CHAR(BIRTHDATE, 'MM')이 반복적으로 들어가는데, 이 수식이 길어질 경우 이또한 보기 안좋을 수 있다.
그럴 경우 아직 완충제로 조금씩 맛보기만 보고있는 서브쿼리를 통해 별칭만으로 정리해줄수 있다.
수식이 길어지면 위의 방법처럼 DEPTH하나를 더 들어가 가독성이 좋게 해줄수 있다.
그룹함수
데이터베이스의 3대장중 1대장이다.
그만큼 어렵고 그 활용도가 매우 잦으니 처음부터 잘 이해하고 들어가야한다.
GROUP BY 절을 이용해 그룹화하는데, 여기엔 칼럼이 올수도, 수식이 올수도 있다.
GROUP에대한 조건은 HAVING절에 명시해야한다.
GROUP을 이용한 출력결과와 DISTINCT를 이용한 출력결과는 당장에보기에 같을 수 있다.
하지만 GROUP은 묶는 거라 COUNT라는 집계함수를 사용하는게 가능한데, DISTINCT는 중복값 제거하는 것이라 집계함수를 사용할 수가 없다.
위의 예제 두개는 같은 결과를 가져온다.
절 처리 순서 상 SELECT절이 제일 마지막이므로 WHERE절에서 그 조건을 명시해줄수도 있다.
위의 예제처럼 GROUP BY에 컬럼이 하나가 아닐수도 있다.
이를 다중컬럼에 의한 GROUPING이라 하는데, 조건이 두개가 된 것이다.
표를 상상하며 생각하는것이 이해하는데 훨씬 편할 것이다.
학과와 학년별 인원수와 평균몸무게를 출력하기 위해 학과, 학년으로 GROUPING을 하였다.
그러면 학과와 학년이 같은 행끼리 한 그룹이 될 것이고 그후 COUNT(*)은 한 그룹내의 행 개수, 즉 그룹에 포함된 모든 학생 수를 의미한다.
평균 또한 해당 그룹의 평균을 낼 것이며 소수점 이하 첫번째 자리에서 반올림하기 위해 ROUND함수를 사용했다.
ROUND함수의 기본값이 소수점 첫째자리에서 반올림이기 때문에 추가적으로 별다른 인자는 사용하지 않았다.
예제를 연습하는데에 있어서 임의로 추가한 데이터에 DEPTNO 및 GRADE가 NULL인 데이터가 있어서 해당 데이터는 IS NOT NULL로 제외하였다.
ROLLUP 연산자와 CUBE연산자는 GROUP BY절에 사용되는 연산자이다.
ROLLUP은 그룹 조건에 따라 전체 행을 그룹화하고 각 그룹에 대한 부분합을 구한다.
CUBE는 ROLLUP에 의한 그룹결과와 그룹의 조건에 따라 그룹조합을 만드는 연산자이다.
말로 설명하면 어려운게 아니라 그냥 어려운 개념이다. 신입개발자에겐 바라지도 않으니 이런게 있구나 하고 넘어가는 정도로 완충해두면 되겠다.
이와 함께 쌍으로 같이 사용되는 함수가 GROUPING함수인데 이는 인수로 지정된 칼럼이 ROLLUP이나 CUBE연산자로 생성된 그룹조합에서 사용되었는지 그 여부를 사용되었을 시 1, 반대의 경우는 0을 반환한다.
GROUPING SETS함수는 조금 다르다.
이 역시 이런 개념이 있다는 것을 알고 넘어가는것으로도 충분하다.
5, 8, 10, 12, 13 행이 ROLLUP으로 인해 생긴 행들이다.
또한 GROUPING함수로 각 칼럼이 사용되었는지 그 여부를 보여주고 있다.
그간 배운 모든 절이 사용된 좋은 예제이다.
처음부터 완벽하게 하지말고 순차적으로 결과를 확인하며 코드를 완성해나가는 것이 데이터베이스를 학습하는 가장 좋은 방법이다.
위의 코드는 완충제로 선생님이 한번 보여주신 코드이다.
서브쿼리, 조인 등 3대장이 다 출현한 코드이니 지금 당장은 어려운게 당연하다.
원래 위 예제의 답은 이렇게 간단하지만, 해당 최대 평균몸무게가 어떤 학과인지 명시해주기 위해 위의 방법을 사용했다.
조인
조인이란 간단하게 말해 FROM절에 대상이되는 테이블이 여러개인 경우를 말한다.
즉 두개 이상의 테이블을 결합하여 사용하는 것인데, 일정부분 겹치는 테이블들을 연관지어 사용하게 된다.
여기서 크게 두가지로,
내부조인 : NULL값을 비포함한다.
외부조인 : NULL값을 포함한다.
로 나뉜다.
학과이름과 학과위치는 DEPARTMENT테이블에 있고 학번과 이름은 STUDENT테이블에 있다.
이 두 테이블을 연결짓는 칼럼은 DEPTNO이므로 이를 활용해 원하는 조건을 쿼리에 만들었다.
위의 예제는 두 테이블에 공통적인 칼럼이 DEPTNO 뿐인데, 이땐 다른방법을 사용할 수 있다.
NATURAL JOIN 키워드를 사용해 조인하는데, 이때 주의할점을 주석해두었다.
NATURAL JOIN은 조인의 대상이되는 모든 테이블들의 겹치는 칼럼명들을 모두 동등비교를 한 후 같을 경우만 출력한다.
만약 겹치는 칼럼명이 너무 많거나 기본키에 해당하는 칼럼들도 겹쳐버리면 아무런 내용도 출력되지 않을 것이기에 사용시에 주의해야한다.
맨위의 예제가 앞서 배운 일반적인 조인이라면,
안시 조인문법(JOIN 키워드를 명시하고 조건을 ON키워드를 이용해 명시한)과 ON키워드가 아닌 USING키워드를 사용한 안시조인문법도 있다.
실제 실무에서는 가독성, 편리함 등의 이유로 안시조인문법을 훨씬 많이 사용하니 익숙해질 필요가 있다.
자바스크립트
let, const키워드
ES5까지는 변수를 선언할 유일한 방법이 var키워드였다.
우리가 여지껏 사용해온 var키워드는 여러 문제를 가지고 있다.
후에 소개할 이런 문제들 때문에 const와 let키워드가 ES6에 추가되었다.
var키워드로 선언한 변수는 중복선언이 가능하다. 이는 호이스팅과도 밀접한 관계가 있는데, 중복 선언되버린 변수의 경우 그 선언부가 자바스크립트 엔진에 의해 var키워드가 없는 것처럼 동작하고, 에러는 발생하지 않는다.
또한 var키워드로 선언한 변수는 함수의 블록만 지역스코프로 인정한다. 즉 if블록이나 for블록 뿐만 아니라 기타 블록 안에서 선언한 변수는 모두 전역변수취급한다.
이런 단점들을 보완하기 위해 나온 키워드가 let과 const이다.
우선 중복선언자체를 막아놓았다.
let이나 const키워드를 이용해 선언한 변수를 똑같은 방법으로 선언하면 문법에러가 발생한다.
또한 let키워드를 이용해 선언한 변수들은 var키워드로 선언된 변수와는 달리 모든 블록을 지역스코프로 인정하는 블록레벨 스코프를 따른다.
또한 기본적인 자바스크립트만의 특징인 호이스팅도 발생하지 않은 것처럼 보이지만 동작한다.
이부분은 단계를 조금만 더 세분화하면 이해할 수 있다.
변수를 선언한 위치보다 위에서 사용했을때, var키워드의 경우 undefined로 초기화되었지만, let키워드로 선언된 변수는 undefined로 초기화되기 전의 상태이다.
즉 선언과 undefined로 초기화단계와, 실제 재할당으로 초기화된 단계를 나누어 보면 let키워드를 사용해 선언한 변수도 선언부가 호이스팅된것이다.
한줄로 정리하자면, let키워드로 선언한 변수는 선언단계와 초기화단계가 분리되어 진행된다.
또한 let키워드로 선언한 변수는 전역객체의 프로퍼티가 아니다.
let 전역변수는 보이지 않는 개념적인 블록내에 존재하게 된다. 이는 23장 실행 컨텍스트에서 자세히 살펴볼 것이다.
const키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 한다.
이 역시 let키워드와 같은 호이스팅을 보인다.
const키워드는 선언한 변수가 상수임을 뜻하며, 이는 자바에서와 마찬가지로 그 값을 재할당할 수 없음을 의미한다.
만약 const키워드로 선언된 변수가 객체를 할당받을 경우 그 주소값을 변경할 수 없다는 뜻이지, 객체의 프로퍼티를 변경하지 못한다는 의미가 아님을 확실히 알고 넘어가야한다.
변수 선언에는 기본적으로 const키워드를 사용하고, let은 재할당이 필요한 경우에 한정해 사용하는 것이 좋다.
17장 생성자함수에 의한 객체생성
객체를 생성하는 가장 간단한 방법은 객체리터럴을 사용하는 방법이다.
하지만 이 방법은 생성해야할 객체가 많아지면 효율적이지 못한 방법이 된다.
객체를 생성하는 방법은 여러가지가 있지만 그 중 생성자함수에 의한 객체생성에 대해 알아본다.
자바에서와 마찬가지로 new연산자와 생성자함수를 이용해 객체를 생성한다.
자바에서 클래스를 만들고 생성자를 정의해 인스턴스를 생성했던 것과 비슷한 방법을 쓰는것이다.
기본적으로 생성자함수는 암묵적으로 this를 반환하지만 명시적으로 원시값을 반환하면 이는 무시되고 원래의 this가 반환된다.
하지만 원시값이 아닌 다른 객체나 배열을 명시적으로 반환하면 this가 반환되지 못하고 return문에 명시한 객체 혹은 배열이 반환된다.
이처럼 생성자함수 내부에서 명시적으로 this가 아닌 다른 값을 반환하는 것은 생성자 함수의 기본 동작을 훼손할 수 있다. 고로 생성자 함수 내부에서 return문을 생략하는것이 안전하니 반드시 그렇게 하도록 하자.
오늘은 여기까지!!!!!
자바에 비해 좀더 광범위하게 쓰이는 this에 감탄하고, 높은 자유도를 가진 것 같은 언어라는 생각이 한번더 들었다.
정확한 로직을 갖는 자바에 비해 자바스크립트는 개발자의 능력에 따라 아웃풋이 천차만별일것 같다는 생각이 든다.