TigerCow.Door


안녕하세요. 문범우입니다.

이번 포스팅에서는 이중 not exists에 관해 예제를 다뤄보도록 하겠습니다.

이번에 다루게 되는 내용에 대해서는 기본적으로 not exists에 대해 동작 방식을 이해해야 수월하게 따라올 수 있습니다.

not exists에 대해 아직 헷갈린다면 아래 글을 먼저 확인해주세요.


[MS SQL Server] #11_ IN / EXISTS / NOT IN / NOT EXISTS 비교


특별히 이번 예제는 블로그를 통해서 연락주신 분에 의해서 다루게 되었습니다.



1. 테이블 정의 및 데이터 정의


먼저 예제를 소개하기에 앞서 사용될 테이블과 데이터를 정의합니다.

총 3개의 테이블(sailors, boats, reserved)을 사용하며 각 테이블에 있는 데이터는 아래 사진과 같습니다.


sailors tablesailors table


boats tableboats table


reserved tablereserved table



테이블에 대해 간략히 소개를 드리자면,

sailors 테이블은 5명의 사람데이터가 입력되어 있습니다. 각 사람에게는 sid라는 고유번호가 주어져 있으며 name값으로 이름이 주어집니다.

boats 테이블은 총 3개의 보트데이터가 입력되어 있습니다. 각 보트에는 bid라는 고유번호가 주어지며 boat_name값으로 이름이 주어집니다.

reserved 테이블은 어떤 사람이 어떤 보트를 예약했는지에 대한 정보를 가진 테이블입니다. 즉 sid에 해당하는 사람이 bid에 해당하는 보트를 예약한 것입니다.



2. 이중 not exists 예제


위와 같은 테이블과 데이터를 기반으로 우리의 목표는 boats 테이블에 있는 모든 보트를 예약한 사람을 구하는 것입니다. 물론 쉽게 알 수 있듯이 sid = 1인, sailor_1이 그 답이 되겠죠.

이 답을 찾기 위해 다음과 같은 쿼리를 사용할 수 있습니다.



위의 쿼리에서는 두번 중첩된 not exists 문, 즉 이중 not exists 문을 이용하여 답을 구하였습니다.


이번 포스팅에서는 위와 같은 쿼리가 어떤 과정으로 답을 도출해내는지 알아보려고 합니다.



3. 이중 not exists 분석


먼저 보다 쉽게 설명하기 위해서 위의 쿼리를 아래와 같이 3개로 나눠보도록 하겠습니다.



위의 그림과 같이 가장 바깥에 있는 쿼리 전체를 1번 쿼리, 그리고 1번 쿼리의 where 문에 있는 서브쿼리를 2번 쿼리, 마지막으로 2번 쿼리의 where 문에 있는 서브쿼리를 3번 쿼리라고 하겠습니다.


not exists문에 대해서 기본적인 내용을 이해한 상태라면 not exists문은 이하 서브쿼리에 값이 아무것도 존재하지 않아야 참이 됩니다.

그럼 데이터 하나씩 그 과정을 자세하게 살펴보도록 하겠습니다.

(아래 모든 그림들에서 3번째 테이블의 pid는 오타입니다. pid가 아닌 sid가 맞습니다.)



쿼리는 위와 같은 3개의 테이블에 대해서 하나씩 데이터를 꺼내 where문에 대해 비교를 실시합니다. 먼저 1번쿼리에 의해서 아래와 같이 sid=1, name=sailor_1인 데이터에 대해 where문 비교를 실시하겠죠.



1번 쿼리의 where문을 비교하기 위해 2번쿼리로 진입합니다. 2번쿼리에서 아래와 같이 bid=101, boat_name=boat_1인 데이터를 대해서 where문을 비교합니다.



이번에는 2번쿼리의 where문을 확인하기 위해 3번 쿼리로 진입합니다. 마지막 3번 쿼리에서는 where을 비교하기 위해 아래와 같이 bid=101, sid=1에 대한 데이터를 비교하기 시작합니다.



그런데 3번 쿼리에서 bid=101, sid=1인 데이터와 1번 쿼리에서 온 sid=1, name=sailor_1, 2번 쿼리에서온 bid=101, boat_name=boat_1인 데이터를 통해 where문을 확인하면 s.sid=r.sid와 b.bid=r.bid 가 모두 참이기 때문에 3번쿼리의 where문이 참이 됩니다. 따라서 3번쿼리에 따른 결과가 아래와 같이 출력됩니다.



이제 다시 2번쿼리로 올라가봅니다. 2번 쿼리의 where문을 보면 not exists(3번쿼리) 입니다. 헌데 방금 위에서 확인하였듯이 3번쿼리에 대한 결과 값이 존재하기 때문에 2번 쿼리의 where문은 거짓이 되죠. 따라서 2번쿼리에서 비교한 bid=101, boat_name=boat_1에 대해서는 2번 쿼리의 결과가 NULL입니다. 이번에는 2번쿼리에서 아래와 같이 bid=102, boat_name=boat_2에 대해서 동일하게 3번쿼리의 비교를 시작합니다.



이번 비교 또한 위와 같이 3번쿼리에서 where문이 참으로 3번쿼리에 대한 결과가 도출 됩니다. 따라서 2번 쿼리에서 비교한 bid=102, boat_name=boat_2에 대해서도 결과가 NULL입니다. 마지막으로 2번쿼리에서 bid=103, boat_name=boat_3에 대해서 비교를 해도 아래와 같이 결과는 같습니다.



즉 이를 통해 2번쿼리에 대해서 모든 데이터의 결과가 NULL입니다.

여기까지의 결과에 한정해서 현재 쿼리 상태를 보면 아래와 같습니다.


위의 그림에서 빨간색으로 나타난 글자와 같이 현재 위의 쿼리는 sailors 테이블의 sid=1, name=sailor_1인 데이터에 대해서 1번쿼리의 서브쿼리 결과를 보다 확인하기 쉽게 나타내주고 있습니다. 위의 쿼리에서 where not exists 이하가 모두 NULL이기 때문에 where문은 결국 참이 됩니다. 따라서, sid=1, name=sailor_1인 데이터는 1번 쿼리의 결과로써 출력이 되는 것 입니다.


동일한 방법으로 1번쿼리에서 두번째 데이터는 왜 출력이 되지 않는지 확인해보겠습니다.



우선 위에서 했던 것과 동일한 방식으로 1번 쿼리에서는 sid=2, name=sailor_2인 데이터에 대해 비교를 시작하며 where문의 서브쿼리인 2번 쿼리로 진입합니다. 2번 쿼리에서는 bid=101, boat_name=boat_1 데이터에 대해서 3번쿼리로 진입하고, 3번 쿼리의 where문에서 참이 되기 때문에 3번 쿼리에 대한 결과는 bid=101, sid=2가 나오게 됩니다. 이에 따라 bid=101, boat_name=boat_1 데이터에 대한 2번 쿼리의 결과는 NULL 입니다.


하지만 위와 같이 2번 쿼리에서 bid=102, boat_name=boat_2인 데이터에 대해서 확인하면 3번 쿼리에서 where문을 참으로 하는 3번째 테이블의 데이터가 없기 때문에 3번 테이블의 결과가 NULL이 됩니다. 이에 따라 2번 쿼리의 where문은 참이 되고, 2번 쿼리에서 bid=102, boat_name=boat_2인 데이터에 대한 결과는 이전과 달리 NULL이 아니라 해당 데이터가 출력되게 됩니다.



위와 같이 2번 쿼리에서 bid=3, boat_name=boat_3인 데이터에 대해 비교했을 때도 동일한 결과가 나와서 해당 데이터에 대한 2번 쿼리의 결과는 NULL이 아니라 bid=103, boat_name=boat_3인 데이터가 나오게 됩니다.

여기까지의 결과를 이전과 같이 한정적으로 쿼리로 살펴보면 다음과 같습니다.



물론 위의 쿼리는 sailors 테이블의 sid=2, name=sailor_2인 데이터에 대해 한정적인 쿼리입니다. 위의 쿼리를 보면 where not exists 이하에 NULL이 아닌 값이 존재합니다. 따라서 where문 이가 거짓이 되어 sid=2, name=sailor_2인 데이터는 출력되지 않습니다.


이후 sailors 테이블의 다른 데이터를 동일한 방법으로 비교하였을 때에도 방금과 같은 이유로 출력되지 않습니다.

즉 처음에 살펴본 sid=1, name=sailor_1인 데이터만 출력되는 것이죠.



이렇게 이번에는 특정 결과를 도출하기 위해 쿼리를 만드는 것을 목적으로 하기 보다 하나의 쿼리에 대해서 그 동작방식을 자세히 알아보았습니다. 특히 이번에 알아본 이중 not exists문에 대해서는 동작방식을 이해하고 살펴보면 쉽게 결과를 예측할 수 있습니다.

물론 특정 결과를 위해 쿼리를 만드는 학습도 중요하지만 이와 같이 특정 쿼리를 보다 자세하게 분석하는 학습 또한 중요합니다.

추가적으로 궁금한 사항이나 잘못된 점은 언제나 댓글 및 이메일로 연락주시면 감사하겠습니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 글에서는 SQL Server에서의 순위함수들(RANK, DENSE_RANK, ROW_NUMBER, NTILE)에 대해서 알아보며 함께 PARTITION BY 절에 대해서도 함께 알아보도록 하겠습니다.



이번 실습 또한 과거 글에서 만들었던 SampleDB를 통해 진행하도록 하겠습니다.


SELECT * FROM employee;



먼저 RANK, DENSE_RANK, ROW_NUMBER 세가지 함수에 대해서 알아보겠습니다. 먼저 각각의 함수에 대해 간략한 설명과 함께 쿼리를 통해 결과를 확인해보고 세가지 함수의 차이에 대해서 함께 알아보도록 하겠습니다.



1. RANK


RANK 함수는 중복 값들에 대해서 동일 순위로 표시하고, 중복 순위 다음 값에 대해서는 중복 개수만큼 떨어진 순위로 출력하도록 하는 함수 입니다.


SELECT empNo, empName, salary,

RANK() OVER (ORDER BY salary DESC) RANK등수

FROM employee;




2. DENSE_RANK


DENSE_RANK 함수는 중복 값들에 대해서 동일 순위로 표시하고, 중복 순위 다음 값에 대해서는 중복 값 개수와 상관없이 순차적인 순위 값을 출력하도록 하는 함수 입니다.


SELECT empNo, empName, salary,

DENSE_RANK() OVER (ORDER BY salary DESC) DENSE_RANK등수

FROM employee;




3. ROW_NUMBER


ROW_NUMBER 함수는 중복 값들에 대해서도 순차적인 순위를 표시하도록 출력하는 함수 입니다.


SELECT empNo, empName, salary,

ROW_NUMBER() OVER (ORDER BY salary DESC) ROW_NUMBER등수

FROM employee;




4. RANK / DENSE_RANK / ROW_NUMBER


위에서 3가지 함수에 대해서 각각 알아보았습니다.

크게 어려운 내용들은 아니기에 각 함수에 대한 설명과 쿼리문 그리고 그에 대한 결과를 보여드렸습니다.

하지만 세가지 함수의 차이에 대해서는 약간 헷갈릴 수 있기에 이번에는 3가지 함수를 동시에 사용해서 차이를 비교해보도록 하겠습니다.


SELECT empNo, empName, salary,

RANK() OVER (ORDER BY salary DESC) RANK등수,

DENSE_RANK() OVER (ORDER BY salary DESC) DENSE_RANK등수,

ROW_NUMBER() OVER (ORDER BY salary DESC) ROW_NUMBER등수

FROM employee;



세가지 함수의 차이를 고려하려면 위 결과의 빨간색 박스를 보면 됩니다.

salary 값이 500으로 중복된 행이 총 3개 존재합니다.


먼저 RANK함수는

중복 값에 대해서 동일한 순위 그리고

중복 값 다음 값에 대해서 중복순위 + 중복값 개수 의 순위를 출력합니다.


DENSE_RANK함수는

중복 값에 대해서 동일한 순위 그리고

중복 값 다음 값에 대해서 중복순위 + 1 의 순위를 출력합니다.


ROW_NUMBER함수는

중복 값에 대해서 순차적인 순위 그리고

중복 값 다음 값에 대해서 또한 순차적인 순위를 출력합니다.



5. NTILE


NTILE 함수도 순위함수로 사용되지만 위에서 사용된 함수들과는 약간 다르게 느껴질 수 있습니다.

NTILE함수는 뒤에 함께 적어주는 숫자 만큼으로 등분을 하는 함수 입니다.

만약 직원들 데이터에 대해서 salary 순서를 기준으로 4등분을 하고자 한다면 다음과 같습니다.


SELECT empNo, empName, salary,

NTILE(4) OVER (ORDER BY salary DESC) NTILE등분

FROM employee;





6. PARTITION BY


PARTITION BY 절 또한 어렵지 않습니다.

만약 위와 같은 데이터에서 단순히 모든 사람의 salary를 순위 매기고 싶은 것이 아니라, 직급별 순위를 매기고 싶다면 어떻게 할까요?

직급 별로 구분을 해서 순위를 매기면 됩니다. 이렇게 특정 속성 별로 구분을 하고자 할 때 PARTITION BY절을 사용하면 됩니다.


SELECT empName, job, salary,

RANK() OVER (PARTITION BY job ORDER BY salary DESC) RANK등수

FROM employee;



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 포스팅에서는 rollup, cube, case, pivot에 대해서 함께 알아보도록 하겠습니다.



먼저 이전의 글에서 만들었던 sample데이터를 통해 실습을 진행해보도록 하겠습니다.


SELECT * FROM employee;




1. ROLLUP


먼저 알아볼 함수는 ROLLUP 입니다.

ROLLUP은 GROUP BY문과 함께 사용되는 함수인데, GROUP BY로 GROUPING된 행들 데이터 총합을 나타는데 사용합니다.

즉, employee테이블에서 부서별 그리고 직급 별 급여 합과 총합을 구하기 위해서 ROLLUP이 사용될 수 있습니다.


SELECT deptNo, job, SUM(salary) 급여총합

FROM employee

GROUP BY deptNo, job with ROLLUP;



사실상 부서별 그리고 직급별 급여의 합을 구하는 것은 SUM함수를 통해서 할 수 있었습니다.

하지만 위의 결과에서 빨간색으로 음영처리해놓은 결과는 이전의 SUM함수를 통해서 얻을 수 없었습니다.

첫번째 빨간색 음영 박스가 의미하는 것은 deptNO이 10인 부서에서 모든 직급(모든 job)의 급여총합을 의미합니다.

즉, deptNO이 10인 행들끼리 job을 모두 감았다(roll up)는 의미로 생각하시면 될 것 같습니다.

그리고 우리가 GROUP BY를 deptNo, job 로 GROUPING하였기 때문에, job으로 ROLLUP된 행 3개와 deptNO으로 ROLLUP 된 마지막 행(15번째 행)까지 총 4개의 추가 행이 결과로 나오게 됩니다.



2. CUBE


이번에는 CUBE에 대해서 알아봅니다.

쉽게 생각하면 CUBE는 ROLLUP 함수의 확장 형태라고 볼 수 있습니다.

우리가 위의 예에서 deptNo, job으로 ROLLUP을 진행하니, deptNo 끼리 job으로 묶인 salary의 총합(3개 행)과 deptNo와 job으로 묶인 salary의 총합(1개행)의 추가 데이터를 얻을 수 있었습니다.

만약 ROLLUP을 job, deptNo으로 진행했다면 어떨까요?

job끼리 deptNo으로 묶인 salary의 총합(6개 행 = job의 종류가 6개)과 job과 deptNo로 묶인 salary의 총합(1개행)의 추가 데이터를 얻을 수 있습니다.

CUBE는 이렇게 GROUPING 할 때 언급한 열의 순서에 따라 나타날 수 있는 ROLLUP의 경우의 수를 모두 나타내주게 됩니다. 그럼 바로 확인해보도록 하겠습니다.


SELECT deptNo, job, SUM(salary) 급여총합

FROM employee

GROUP BY deptNo, job with CUBE;



위의 결과를 보시면 먼저 3행은 과장 직급의 급여총합을 구한 것이며, 동일하게 5행, 9행, 13행, 15행, 17행은 각 직급별 급여총합을 나타내고 있습니다.

그리고 18행은 모든 deptNo와 job의 급여 총합을 나타내주고 있으며, 19행, 20행, 21행은 deptNo별 급여총합을 나타내고 있습니다.

위의 쿼리문을 아래와 같이 하면 행의 순서는 바뀔 수 있지만 결과는 동일합니다


SELECT deptNo, job, SUM(salary) 급여총합

FROM employee

GROUP BY job, deptNo with CUBE;



3. CASE


이번에 알아볼 CASE문은 C언어나 Java와 같은 프로그래밍 언어에서 사용되는 if ~ else ~ 문 또는 switch 문과 개념적으로 동일합니다.

기본적인 형식은 아래와 같습니다.


CASE when 조건식1 then 결과 1

          when 조건식1 then 결과2

          ...

          [ELSE 결과]

END [AS 칼럼 명]


여기서 대괄호로 표시된 것들은 생략할 수 있습니다.


CASE문은, 우리가 employee 테이블에서 부서별로 부서명을 직접 나타내고 싶을 때와 같은 경우에 사용할 수 있습니다. 부서번호가 10인 경우 전산부, 20인 경우 인사부, 30인 경우 경리부, 40인 경우 영업부로 나타내고 이 외에는 미정이라고 나타내보도록 합시다.


SELECT empName, deptNo,

CASE WHEN dpetNo = 10 THEN '전산부'

WHEN deptNo = 20 THEN '인사부'

WHEN deptNo = 30 THEN '경리부'

WHEN deptNo = 40 THEN '영업부'

ELSE '미정'

END AS 부서명

FROM employee;



위와 같이 우리가 조건을 설정한 대로 부서명이 올바르게 출력되었습니다.

조건식에는 범위에 대한 조건도 설정할 수 있습니다.


만약 부서번호가 20이하인 경우는 부서위치가 1층, 20초과인 경우에는 부서위치가 2층인 것으로 나타내고자 하면 다음과 같이 할 수 있습니다.


SELECT empName, deptNo,

CASE WHEN deptNo <= 20 THEN '1층'

WHEN deptNo > 20 THEN '2층'

END AS 부서위치

FROM employee;




4. PIVOT / UNPIVOT


마지막으로 알아볼 것은 PIVOT과 UNPIVOT입니다.

먼저 PIVOT에 대해서 알아보도록 하겠습니다.

PIVOT은 행으로 되어 있는 데이터를 열로 변환해서 표현하는 함수입니다.


우리가 가지고 있는 employee 테이블에서 열을 deptNo과 각 직급으로 나타내어 그 값을 표현하려면 어떻게 해야 할까요? 기존의 직급 데이터는 'job'이라는 속성에 행으로써 존재 했습니다. 하지만 사원, 부장 과 같이 행으로 되어있던 데이터를 열로 나타내려면 PIVOT을 사용하면 됩니다.

PIVOT문의 기본 형태는 다음과 같습니다.


SELECT [PIVOT열1], [PIVOT열2], ...

FROM 테이블명

PIVOT(나타내고자하는 값, FOR 행->열로 바꿀 열 IN ([PIVOT열1], [PIVOT열2], ...)) as 별칭


PIVOT문은 조금 어려울 수 있기 때문에 바로 실제 쿼리를 보면서 이해하시는 것을 추천드립니다.

위에서 이야기한 바를 쿼리로 나타내면 다음과 같습니다.


SELECT deptNo, [사원], [대리], [과장], [부장], [차장], [사장]

FROM employee

PIVOT(SUM(salary) FOR job In([사원], [대리], [과장], [부장], [차장], [사장])) AS job

ORDER BY deptNo;



위와 같이 행으로 되어있던 값을 열로 나타내어 테이블의 형태를 재구축 할 수 있습니다.

UNPIVOT과 같은 경우도 PIVOT과 활용법이 동일하지만 PIVOT이 행->열의 방식이었다면 UNPIVOT은 열->행의 방식인 것만 고려하면 됩니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

지난 글에서 기초적인 SELECT문을 통해 데이터를 조회하는 방법에 대해서 알아보았습니다.

이번 포스팅에서는 SELECT문에 WHERE절을 추가하여 특정 조건에 부합하는 데이터들만 조회하는 방법에 대해서 알아보도록 하겠습니다.


데이터베이스 및 테이블들은 지난 글에서 만든 샘플데이터를 그대로 이용합니다. 해당 샘플 데이터가 없는 분들은 아래 글에서 쿼리를 통해 샘플데이터를 생성하고 진행해주세요.


[MS SQL Server] #5_SELECT문 기초



1. WHERE문 기초


먼저 아래와 같은 기본 SELECT문을 통해서 employee 테이블의 모든 데이터를 조회해보도록 합시다.


SELECT * FROM employee;


그런데 만약 위와 같이 모든 정보를 얻고 싶은 것이 아니라, job의 값이 '사원'인 데이터에 대해서만 조회하고 싶을 때는 어떻게 할까요?

또는 salary가 500 이상인 데이터만 조회하고 싶을 때는 어떻게 해야 할까요?


이와 같이 테이블에서 특정 조건에 부합하는 데이터만 조회하고 싶을 때 사용하는 것이 WHERE절 입니다.


그럼 바로 WHERE절을 사용해보도록 합시다.

먼저 job이 사원인 데이터만 조회하는 쿼리는 다음과 같습니다.


SELECT * FROM employee

WHERE job = '사원';



위의 결과와 같이 job이 '사원'인 데이터만 조회되었습니다.


그럼 같은 방법으로 salary가 500 이상인 데이터도 조회해보도록 합시다.


SELECT * FROM employee

WHERE salary >= 500;



위와 같이 salary가 500이상인 데이터만 조회되었습니다.


WHERE 절에서 사용되는 기본적인 연산자는 다음과 같습니다.


대소를 비교할 때 사용되는 >, <, >=, <= 와 같은 것들이 있으며,

같음을 나타내는 = 와 서로 다름을 나타내는 != 또는 <>이 있습니다.


그런데 여러개의 조건을 함께 사용해야 하는 경우는 어떻게 해야할까요?



2. 논리연산자(and / or)의 사용


여러개의 조건을 함께 사용해야 한다는 것은 다음과 같은 상황일 것 입니다.


'사장' 직급이 아니면서, salary가 500 이상인 데이터에 대해서 조회하시오. 또는

commission을 포함한 연봉이 5500만원 이하이거나 '사원' 직급인 데이터를 조회하시오.


이러한 경우는 어떻게 할까요?

바로 여러개의 조건을 동시에 사용하면 되는데, 이럴 때 사용하는 것이 논리 연산자 입니다.

and 논리 연산자는 좌,우측의 조건을 동시에 만족해야 할 때 사용되며,

or 논리 연산자는 좌,우측의 조건중 하나만 만족하면 될 때 사용합니다.


그럼 바로 쿼리문으로 확인해보도록 하겠습니다.

'사장' 직급이 아니면서, salary가 500 이상인 데이터에 대해서 조회하는 쿼리는 다음과 같습니다.


SELECT * FROM employee

WHERE job != '사장'

AND salary >= 500;



위와 같이 우리가 기대한 결과가 잘 나온 것을 확인할 수 있습니다.


그럼 이번에는 OR연산자를 이용해보도록 합시다.

commission을 포함한 연봉이 5500만원 이하이거나 '사원' 직급인 데이터를 조회하는 쿼리는 다음과 같습니다.


SELECT * FROM employee

WHERE (salary * 12) + isnull(commission,0) <= 5500

OR job = '사원';



위의 쿼리에서는 지난 시간에 배운 isnull() 함수를 이용하여 연봉을 계산하고 해당 값을 WHERE절 에서 그대로 사용하였습니다.

위와 같이 WHERE절에서 연산도 가능하니 참고하시기를 바랍니다.



3. BETWEEN A AND B


이번에 배워볼 것은 위와 같이 WHERE절에서 사용되는 BETWEEN A AND B 구문입니다.

만약 salary가 300이상 500이하인 데이터에 대해서 조회하려면 어떻게 해야할까요?

우리가 위에서 배운 내용대로라면, 아래와 같은 쿼리가 될 것입니다.


SELECT * FROM employee

WHERE salary >= 300

AND salary <= 500;


하지만 BETWEEN A AND B 구문을 이용하면 다음과 같이 쿼리를 작성하면 됩니다.


SELECT * FROM employee

WHERE salary BETWEEN 300 AND 500;



실제로 같은 결과를 가져오지만 이전의 쿼리보다 보다 간결하고 직관적임을 알 수 있습니다.



4. IN


마지막으로 배워볼 구문은 IN입니다.

만약 salary가 300, 400, 500, 600인 데이터를 조회하려면 어떻게 해야할까요?

이전의 학습을 기반으로 쿼리를 작성해보면 다음과 같습니다.


SELECT * FROM employee

WHERE salary = 300

OR salary = 400

OR salary = 500

OR salary = 600;


하지만 IN 구문을 이용하면 다음과 같이 쿼리를 작성할 수 있습니다.


SELECT * FROM employee

WHERE salary IN (300,400,500,600);



IN구문을 활용함으로써 OR을 통한 이전의 쿼리보다 더 간결하고 직관적임을 알 수 있습니다.



이번 포스팅에서는 WHERE 절을 이용해서 조건에 부합하는 데이터 조회방법에 대해서 알아보았습니다.

사실 WHERE절 없이 SELECT를 활용하는 경우보다는 WHERE절을 통해 원하는 데이터만 조회할 때가 더 많다고 생각됩니다. 따라서 위에 나온 쿼리문들 이외에도 다양하게 시도해보고 쿼리문을 만들어보시길 바랍니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 포스팅에서는 MS SQL Server에서 데이터를 다루는 기초적인 쿼리들에 대해서 알아보도록 하겠습니다.

구체적으로는 create table, insert, alter에 대해서 다뤄볼 예정입니다.



1. CREATE DATABASE


먼저 우리가 이번 실습을 진행할 데이터 베이스를 만들어보도록 합니다.


CREATE DATABASE MEMBER_TEST;


위의 쿼리로 MEMBER_TEST라는 이름의 데이터베이스를 만듭니다.


그리고 이후 아래 쿼리를 통해 해당 데이터베이스에서의 작업을 시작합니다.


USE MEMBER_TEST;




2. CREATE TABLE


이제 우리가 데이터를 다뤄볼 첫번째 테이블을 만들어 보도록 하겠습니다.

테이블을 만드는 쿼리문은 기본적으로 아래의 형태를 가지고 있습니다.


CREATE TABLE <TABLE_NAME>(

<COLUMN1> <DATA_TYPE> [CONTRAINTS],

<COLUMN2> <DATA_TYPE> [CONTRAINTS],

<COLUMN3> <DATA_TYPE> [CONTRAINTS], ...

);


정확히 이해가 가지 않는다면 먼저 아래의 쿼리를 보고 다시 설명드리겠습니다.



CREATE TABLE T_MEMBER(

id INT IDENTITY(1,1),

name VARCHAR(10)

);


위의 쿼리문에 대해 한번 자세히 알아보도록 합시다.


먼저 첫번째에서는 CREATE TABLE T_MEMBER(~)로 되어있습니다.

간단합니다, 단순히 T_MEMBER라는 이름의 테이블을 만든다는 뜻 입니다.

그런데 추가적으로 괄호가 있는 이유는, 테이블에 들어갈(또는 테이블이 포함할) 데이터에 대한 정의가 필요하기 때문입니다.


그럼 이어서 두번째 줄을 보겠습니다.

두번째 줄에는 id INT IDENTITY(1,1) 라고 되어있습니다.

여기서 id라는 것은 해당 컬럼의 이름입니다. 그리고 이어서 있는 INT는 해당 컬럼의 데이터 타입을 이야기합니다.

데이터 타입에는 숫자형을 나타내는 INT, 그리고 바로 아래에서 사용되는 문자열을 담는 VARCHAR와 같은 것들이 있습니다.

그리고 그 뒤에 있는 IDENTITY(1,1) 해당 컬럼에 특정 제약조건(contraint)를 준 것인데, 이에 대해서는 조금 이따가 다시 살펴보도록 합시다.


마지막으로 세번째 줄을 확인하시면, 두번째 줄에서 본 것과 동일합니다.

name이라는 컬럼 이름을 설정해주고 있으며 해당 컬럼의 데이터 타입은 VARCHAR(10)인 것 입니다.


그럼 마지막으로 IDENTITY에 대해서 알아보고 테이블 생성문(CREATE TABLE)에 대해 마무리해보도록 합시다.


먼저 우리가 컬럼을 정의할 때 특정 제약조건들을 설정해줄 수 있습니다.

대표적으로는 NULl값을 가지지 못하게 NOT NULL을 설정하거나, 중복값을 갖지 못하게 하는 UNIQUE, 또는 기본값을 설정해주는 DEFAULT 등이 있습니다.

그리고 IDENTITY도 제약조건중에 하나입니다.

IDENTITY는 데이터가 추가될 때 마자 자동으로 증가되는 값을 가질 수 있도록 하는 제약조건입니다.

IDENTITY(1,1)에서 두개의 숫자 1이 나타내는 것은 어떤 값에서 시작해서 얼마나 숫자가 증가할지를 의미합니다.

즉, IDENTITY(start number, increment number) 입니다.

따라서 우리가 위의 쿼리에서 설정한 제약조건은, id컬럼의 값이 1부터 시작해서 자동으로 1씩 증가하여 저장되는 제약조건입니다.



3. INSERT INTO


이제 이렇게 만들어진 테이블에 실제로 데이터를 입력해보도록 하겠습니다.

테이블에 데이터를 입력할 때 사용하는 쿼리문은 INSERT INTO 입니다. 해당 쿼리문에 대해서 자세히 알아보도록 하겠습니다.


INSERT [INTO] <TABLE NAME>

[(COLUMN NAME1, COLUMN NAME2, ...)] VALUES (VALUE1, VALUE2, ...);


위와 같은 형태를 띄고 있는 INSERT 문은 우리가 원하는 칼럼에만 데이터를 입력하거나, 모든 칼럼에 데이터를 입력할 수 있습니다. 이 말이 아직 제대로 이해가지 않아도, 아래 예제 쿼리들을 실행시켜보면서 이해해보도록 합시다.


INSERT INTO T_MEMBER (name) VALUES ('김범우');

INSERT T_MEMBER (name) VALUES ('이범우');

INSERT INTO T_MEMBER VALUES ('한범우');

SELECT * FROM T_MEMBER;


위와 같은 4개의 쿼리를 실행하고 나면 아래와 같은 결과를 얻을 수 있습니다.



3개의 INSERT 문이 약간씩 차이가 존재하지만, 결국 VALUES 뒤의 데이터값이 입력되고 있음을 알 수 있으며, 우리가 이전에 테이블을 정의할 때 id 컬럼에 적용한 IDENTITY가 정상적으로 적용되고 있음도 확인할 수 있습니다.


그럼 이제 한번 더 새로운 테이블을 만들어 보고 데이터를 입력해보도록 하겠습니다.



4. CREATE, INSERT 복습


먼저 아래와 같은 쿼리를 통해 T_PRODUCT 테이블을 만들어보겠습니다.

CREATE TABLE T_PRODUCT(

product_code VARCHAR(5) CONSTRAINT pk_code PRIMARY KEY,

product_name VARCHAR(20) NOT NULL,

product_price VARCHAR(10) DEFAULT '0',

product_remark VARCHAR(100)

);  


각각의 컬럼에 대해 설정된 제약조건들에 대해서만 한번 더 짚고 넘어가겠습니다.

product_code는 pk_code라는 이름으로 기본키(Primary key) 설정을 하였습니다.

기본키라 함은, 해당 테이블 내에 존재하는 여러 행(레코드)들 중에서 유일하게 식별가능한 값을 의미합니다.

따라서 null값이 들어갈 수 없고, 다른 값과 중복될 수 없는 특징이 있습니다.


두번째로 product_name은 not null 조건을 통해 null 값이 들어갈 수 없도록 설정하였습니다.


product_price 는 default값을 설정해 줌에 따라서 아무 값도 입력되지 않을 경우 0이라는 값으로 설정되도록 하였습니다.


그리고 마지막 product_remark 컬럼은 어떠한 제약조건도 설정하지 않았습니다.


이렇게 만든 T_PRODUCT 테이블에 직접 데이터를 입력해보도록 하겠습니다.


INSERT INTO T_PRODUCT (product_code, product_name, product_price, product_remark)

VALUES ('A001', '청소기', '1000000', '무선');


INSERT T_PRODUCT (product_code, product_name)

VALUES ('A002', '냉장고');


SELECT * FROM T_PRODUCT;


먼저 두개의 INSERT 문을 통해 2개의 데이터를 입력해보고 아래와 같은 결과를 확인해보겠습니다.



첫 번째 INSERT 문에서는 4개의 컬럼에 모두 값을 입력해주었습니다.

그와 다르게 두번째에서는 prudct_code와 product_name에만 값을 입력하였습니다.

그리고 결과를 보니, 값을 입력하지 않은 product_price는 default 값이 자동으로 입력되었고, 아무런 설정도 하지 않은 product_remark 에는 null 값이 입력된 것을 확인할 수 있습니다.


그럼 우리가 not null로 설정한 product_name에 아무런 값도 입력해주지 않으면 어떻게 될까요?

바로 시도해보겠습니다.


INSERT INTO T_PRODUCT (product_code, product_remark)

VALUES ('A003', '이름없는 제품');


위의 쿼리문을 실행시키면 아래와 같이 에러가 발생합니다.



에러 내용을 읽어보면 우리가 값을 설정해주지 않은 product_name에 null이 입력될 수 없다는 내용입니다.

우리가 테이블을 만들 때 설정한 제약조건 때문인 것이죠.

이와 같이 기본키로 설정한 product_code 또한 아무런 값을 입력해주지 않으면 동일한 에러가 출력될 것입니다.



5. ALTER


그런데, 우리가 처음 만들었던 테이블에 대해 몇가지 수정을 하고 싶다면 어떻게 할까요?

바로 ALTER문을 이용해 테이블의 컬럼에 대해 변경, 추가, 삭제를 진행할 수 있습니다.


그럼 먼저, VARCHAR(10) 으로 설정되어 있던 product_price에 대해서 설정을 해보겠습니다.


ALTER TABLE T_PRODUCT

ALTER COLUMN product_price VARCHAR(20);


위의 ALTER 문을 통해서 VARCHAR(10) 로 되어있던 product_price를 VARCHAR(20) 으로 확장시킬 수 있습니다.


그런데 VARCHAR(20)으로 되어있는 컬럼을 더 작게 축소하는 것은 가능할까요?

정답은 가능할 때도 있고, 불가능할 때도 있습니다.

만약 해당 컬럼에 VARCHAR(10)의 크기를 넘는 값을 가지는 행이 존재한다면 해당행의 데이터 손실이 발생하는 것을 막기위해 컬럼의 변경이 불가합니다.

하지만 VARCHAR(10)의 크기를 넘는 값을 가지는 행이 없을 땐 가능합니다.


추가적으로 컬럼을 추가할 때에는,


ALTER <TABLE_NAME>

ADD COLUMN <COLUMN NAME> <DATA TYPE> [<CONSTRAINTS>];


와 같은 구문으로 추가할 수 있습니다.


비슷하게 컬럼을 삭제할 때에는,


ALTER <TABLE_NAME>

DROP COLUMN <COLUMN NAME>;

와 같은 구문으로 삭제할 수 있습니다.


이렇게 해서 테이블을 만들고, 데이터를 입력하고, 만들었던 테이블 컬럼에 대해 수정, 추가, 삭제하는 쿼리문에 대해서 알아보았습니다.

추가적으로 궁금한 점이 있거나 잘못된 점들에 대해서는 언제든지 말씀해주시면 감사하겠습니다.





블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요

안녕하세요. 문범우입니다.

이번 포스팅에서는 SQL Server 에서의 데이터 타입과 SQL에 대해서 간단하게 알아보고, 직접 데이터베이스를 구축해보는 실습 과정을 진행하도록 하겠습니다.

 

 


1. 데이터 타입(DataType)

 

SQL Server에서 사용하는 데이터 타입과 그 범위는 아래와 같습니다.

 

- 정수타입

tinyint : 0~255

smallint : -32768 ~ 32767

int : -2^31 ~ 2^31 - 1

 

- 날짜 시간 타입

datetime : 1753-1-1 ~ 9999-12-31

smalldatetime : 1900-1-1 ~ 2079-6-6

 

- 문자타입

char[(n)] : 고정형 길이

varchar[(n)] : 가변형 길이

 

물론 이 외에도 다른 데이터 타입이 존재하지만, 현재 학습하는 과정에서 기초적으로 알아두어야 할 것들에 대해서만 나열해보았습니다.

 

2. SQL(Structured Query Language)

 

SQL은 기능에 따라서 총 3가지로 나누어 볼 수 있습니다.

 

- 데이터 정의어(DDL) : CREATE, ALTER, DROP 등

   테이블이나 테이블 간의 관계를 생성 및 수정하는데 사용하는 것

 

- 데이터 조작어(DML) : SELECT, INSERT, DELETE, UPDATE 등

   테이블에 데이터를 검색하거나 삽입, 삭제, 수정하는데 사용하는 것

 

- 데이터 제어어(DCL) : GRANT, REVOKE 등

   데이터에 대한 사용 권한을 제어하거나 관리하는 데 사용하는 것

 

위와 같이 기능에 따라 총 3가지로 나누어 볼 수 있으며, 각각에 대해서는 앞으로 학습을 하며 좀 더 자세히 알아보도록 하겠습니다.

 

 

3. 데이터베이스 구축하기

 

이제 실제로 SQL Server에 데이터베이스를 구축해보도록 하겠습니다.

먼저 지난번에 설치한 SSMS를 실행시켜서 SQL Server에 연결시켜서 아래와 같은 화면이 보이도록 합니다.

 

데이터베이스를 구축하는 방법은 총 2가지가 존재하는데 이에 대해서 실습을 진행해보도록 하겠습니다.

2가지 방법은 이번 글에서 알아볼 개체탐색기를 이용하는 방법과 다음 포스팅에서 알아볼 Transact-SQL을 이용한 방법입니다.

- 데이터베이스 만들기

먼저 첫번째로 이번 글에서는 좌측에 보이는 개체탐색기를 이용합니다.

개체탐색기에서 데이터베이스에 우클릭을 하여 새 데이터베이스를 클릭하여 아래와 같은 화면이 뜨도록 합니다.

 

이제 여기서 새롭게 만들 데이터베이스 이름을 설정합니다.

또한 소유자는 현재 기본값으로 되어 있는데 이러한 경우 기본적으로 연결되어있는 유저가 소유자가 됩니다.

 

이렇게 설정하고 확인을 눌러주고 나면 좌측의 개체탐색기의 데이터베이스 내부에 Text01이라는 데이터베이스가 새로 생긴것을 확인할 수 있습니다.

또한 Test01 내부를 보면 테이블, 뷰와 같은 것들이 자동으로 생긴것을 볼 수 있습니다.

 

- 테이블 만들기

그럼 이어서 Test01에 새로운 테이블을 만들어보도록 하겠습니다.

이번에는 데이터베이스 > Test01 > 테이블을 우클릭 하여 테이블을 클릭하여 아래와 같은 창이 뜨도록 합니다.

새롭게 뜬 창을 보면 열이름과 데이터 형식 등을 기입할 수 있도록 되어 있습니다.

해당 창에 아래 사진과 같이 열과 데이터 형식, Null 허용 체크를 맞추어 채워보도록 합니다.

위와 같이 3개 필드를 추가하셨다면 Ctrl+s 또는 화면 상단의 저장버튼을 눌러서 저장하는데 이때 테이블 이름은 member 로 설정하도록 합니다.

 

정상적으로 저장이 되었다면, 좌측 개체탐색기에서 Test01 > 테이블에 dbo.member 라는 것이 새로 생긴것을 확인할 수 있습니다.

 

- 기본키 설정

이제 특정 칼럼에 대해서 기본키설정을 해보겠습니다.

 

먼저 기본키란, 간단히 얘기해서 동일 테이블 내에서 행을 유니크하게 구별할 수 있는 값을 이야기합니다.

따라서 기본키로 설정된 값은 서로 중복될 수 없으며 null이 허용되지 않습니다.

 

 dbo.member 탭에서 id를 우클릭하면 아래 사진과 같이 여러가지가 나오는데 이중에서 기본 키 설정을 클릭합니다.

 

 

그럼 id라는 값 좌측에 노란색 열쇠모양이 생긴 것을 확인 할 수 있습니다.

 

이제 새로운 테이블을 만들어 보도록 하겠습니다.

방법은 위에서 했던 것과 동일하며 아래와 같이 3개의 컬럼을 가지도록 테이블을 만들어 줍니다.

 

그리고 테이블 이름은 Product로 설정합니다.

 

이렇게 하여 새로 테이블을 추가하였는데, 아까와 달리 좌측 개체탐색기에 dbo.Product 테이블이 보이지 않는다면 F5를 눌러 새로고침하거나, 개체탐색기 창의 상단에 있는 새로고침 버튼을 눌러줍니다.

 

- 데이터 추가

이제 member 테이블에 데이터를 추가해보도록 하겠습니다.

개체탐색기에서 dbo.member 를 우클릭하고 상위 200개 행 편집을 선택합니다.

 

그리고 아래 사진과 같이 데이터를 입력합니다.

데이터를 입력때는 Tab 키를 이용하면 편리하게 입력이 가능하고, 위의 사진에서 빨간색 느낌표가 있는 이유는 아직 해당 행의 데이터가 저장되지 않았다는 의미입니다.

다음 행으로 넘어가게 되면 자동적으로 이전 행이 추가(저장)됩니다.

그리고 특정행을 삭제하기 위해서는 id 열의 좌측에 빈공간을 우클릭하여 삭제를 누르시면 됩니다.

 

그럼 이번에는 Proudct 테이블에 아래 사진과 같은 데이터를 입력해보도록 합니다.

 

- 데이터 확인

이제 실제로 쿼리문을 통해 데이터가 정상적으로 입력되었는지 확인해보도록 하겠습니다.

 

SSMS 상단에보면 새쿼리 라는 메뉴가 있는데 이것을 클릭합니다.

그리고 아래 사진과 같이 Test01 데이터베이스가 선택되어있는지 확인합니다.

 

그럼 이제 새롭게 열린 쿼리 창에 쿼리문을 작성해보도록 하겠습니다.

 

쿼리문에 대해서는 추후에 공부하도록 하고, 지금은 단순히 데이터가 입력되었는지를 확인하는 것이니, 쿼리문에 대해 정확히 알지 못해도 일단 따라서 입력하겠습니다.

 

select * from member;

 

 위의 쿼리문을 입력하고 F5 버튼을 눌러서 쿼리문을 실행시키면 아래와 같은 결과가 나옵니다.

 

즉, 우리가 좀전에 입력한 3개의 데이터가 잘 입력된 것을 확인할 수 있습니다.

 

동일한 방식으로 아래 쿼리를 통해 Product 테이블에 추가한 데이터도 확인할 수 있습니다.

 

select * from Product;

 

 


이렇게 해서 기초적인 데이터베이스 구축방법에 대해서 실습과정을 진행하였습니다.

기존의 다른 데이터베이스에 대해서 공부하셨던 분들은 매우 쉽게 느껴졌을 것이라 생각합니다. 하지만 SQL Server를 사용하기 위해 SSMS를 잘 다루는 것도 중요하니, 꼭 한번씩 실습과정을 진행하시기를 추천드립니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번에는 지난 포스팅에 이어서 MySQL의 'SELECT 조건에 따른 데이터 검색'에 대한 명령어를 알아보겠습니다.




SELECT (속성1, 속성2, … ) FROM (테이블명) WHERE (조건식);

(조건식)에 의해 해당하는 행을 선택하고 (속성1, 속성2, … )에 의해 열을 선택합니다.

 

SELECT * FROM (테이블명);

WHERE 조건문이 없으므로 모든 행을 선택하고, *(: 모든)을 통해 모든 열을 선택합니다.

(테이블명)의 이름을 가진 테이블을 확인하는 명령어입니다.

 

SELECT * FROM (테이블명) WHERE (조건1) AND (조건2);

(테이블명)의 테이블에서 (조건1) (조건2)를 모두 만족하는 행의 모든 열을 선택합니다.

 

SELECT * FROM (테이블명) WHERE (속성1) BETWEEN (1) AND (2);

(테이블명)의 테이블에서 (속성1)의 값이 (1)(2) 사이인 행의 모든 열을 선택합니다.

 

          - 참고

           아래 두 명령어를 비교합니다.

           SELECT * FROM (테이블명) WHERE age > 19 AND age < 30;

           SELECT * FROM (테이블명) WHERE age BETWEEN 19 AND 30;

           두 명령어를 통한 결과 값은 같지만 성능은 BETWEEN을 사용한 명령어가 더 좋습니다.

            

           단순히 AND만 사용한 첫번째 쿼리는

           전체 데이터에서 age19보다 큰 값과 30보다 작은 데이터를 각각 구해 이들의 교집합 값을 구하는 연산이며

           BETWEEN을 사용한 두번째 쿼리는

           age라는 속성에서 19라는 값부터 시작하여 30이라는 값보다 작은 값을 찾는 연산이기 때문입니다.

 

SELECT * FROM (테이블명) WHERE (조건1) OR (조건2);

(테이블명)의 테이블에서 (조건1) (조건2) 중 어떤 하나라도 만족하는 행의 모든 열을 선택합니다.

 

SELECT * FROM (테이블명) WHERE (속성1) IN (조건1, 조건2, … );

(테이블명)의 테이블에서 (속성1)의 값이 (조건1)이거나 (조건2) 인 행의 모든 열을 선택합니다.

 

          - 참고

           IN을 사용한 구문 또한 BETWEEN을 사용한 구문과 같이 OR보다 성능이 좋습니다.

           아래 두 쿼리를 비교합니다.

 SELECT * FROM (테이블명) WHERE age = 19 OR age = 20 OR age = 21;

           SELECT * FROM (테이블명) WHERE age IN (19,20,21);

           두 쿼리 모두 같은 결과를 출력하지만 IN을 사용한 두번째 쿼리가 성능이 좋습니다.

 

          - 참고

          AND 연산이 OR 연산보다 우선순위가 높습니다.

          , age19 또는 20인 열과 birth1998 또는 1999인 행의 모든 열을 선택하려면

          SELECT * FROM (테이블명) WHERE age = 19 OR age = 20 AND birth = 1998 OR birth = 1999;

가 아닌

SELECT * FROM (테이블명) WHERE (age = 19 OR age = 20)AND(birth = 1998 OR birth = 1999);

를 입력해야 합니다.

 

SELECT * FROM (테이블명) WHERE NOT (조건1);

(테이블명)의 테이블에서 (조건1)을 만족하지 않는 행의 모든 열을 선택합니다.


SELECT * FROM (테이블명) WHERE (속성1) LIKE ‘A_’;

(테이블명)의 테이블에서 (속성1) ‘A+1글자값을 가진 행의 모든 열을 선택합니다.

 

SELECT * FROM (테이블명) WHERE (속성1) LIKE ‘A__’;

(테이블명)의 테이블에서 (속성1) ‘A+2글자값을 가진 행의 모든 열을 선택합니다.


          - 참고

          위의 _ 관련 쿼리의 예제입니다.

          


SELECT * FROM (테이블명) WHERE (속성1) LIKE ‘A%’;

(테이블명)의 테이블에서 (속성1) ‘A’로 시작하는 값을 가진 행의 모든 열을 선택합니다.


SELECT * FROM (테이블명) WHERE (속성1) LIKE ‘%A’;

(테이블명)의 테이블에서 (속성1) ‘A’로 끝나는 값을 가진 행의 모든 열을 선택합니다.

 

SELECT * FROM (테이블명) WHERE (속성1) LIKE ‘%A%’;

(테이블명)의 테이블에서 (속성1) ‘A’를 포함하는 값을 가진 행의 모든 열을 선택합니다.

 

          - 참고

             위의 % 관련 쿼리의 예제입니다.

 


SELECT * FROM (테이블명) ORDER BY (속성1) (순서);

(테이블명)이란 테이블에서 (속성1)(순서)에 따라 모든 열을 출력합니다.

이따 (순서)에는 DESC(내림차순) 또는 ASC(오름차순)을 입력하며 생략했을시의 default 값은 ASC(오름차순) 입니다.

 

SELECT (속성1) AS ‘별명1’, (속성2) AS ‘별명2’ FROM (테이블명);

(테이블명)이란 테이블에서 (속성1)은 별명1이란 이름으로, (속성2)는 별명2라는 이름으로 두개의 열을 출력한다.

 

SELECT DISTINCT (속성1), (속성2), … FROM (테이블명);

(테이블명)이란 테이블에서 (속성1), (속성2), … 를 선택하는데 이때 중복되는 값은 제외합니다.

 

          - 참고

             DISTINCT 관련 쿼리를 예제를 통해 확인합니다. 두 명령어에 따른 출력 값의 차이를 확인하세요.


             기본테이블

 


DISTINCT 쿼리에 따른 차이


 


이렇게 해서 MySQL에서 SELECT 조건에 따른 데이터 검색에 관한 명령어를 알아보았습니다.

다음 포스팅에서부턴 특정 예제를 기준으로 하여 명령어를 알아보도록 하겠습니다.

피드백이나 문의사항은 댓글 및 이메일(doorbw@outlook.com)을 이용해주세요 :)

 

 

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요.

데이터베이스를 학교에서 공부중에 있는데 MySQL을 사용하여 수업을 하고 있습니다.

따라서 MySQL에서 사용되는 명령어들을 정리할겸 포스팅을 진행하려 합니다.

각각의 명령어들을 최대한 순서(?)에 맞춰서 의미들을 설명하려하는데

부족한 점이 있거나 추가적인 명령어들이 있다면 덧글로 피드백 해주세요 :)


이번 포스팅에서 공부해볼 내용은 'Database 및 Table 생성 / 확인 / 제거 / 수정' 에 대한 명령어 입니다.

다음 포스팅에서는 '조건에 따른 데이터 검색'에 대한 명령어를 알아보겠습니다.


CREATE DATABASE 데이터베이스명 default CHARACTER SET UTF8;

(데이터베이스명)이라는 데이터 베이스를 생성하고 한글을 사용할 수 있는 UTF8로 문자열을 저장

 

GRANT ALL PRIVILEGES ON (데이터베이스명).* TO (사용자)@localhost INDENTIFIED BY ‘(비밀번호)’;

GRANT는 사용자에게 데이터베이스의 사용권한을 적용하는 구문입니다.

ALL PRIVILEGES 는 데이터베이스에 대한 모든 권한을 의미합니다. (DB 삭제 또한 가능)

ON (데이터베이스명).* 은 권한 대상 데이터베이스의 테이블을 설정합니다. .* 를 통해 모든 테이블을 의미합니다.

TO (사용자)@localhost 는 사용 권한을 받는 사용자를 지정합니다. 없는 유저라면 새롭게 생성하며 localhost는 말 그대로 로컬에서만 연결 가능함을 뜻합니다.

(localhost가 아닌 외부에서 접근하려고 한다면 접근권한을 따로 설정해 주어야 합니다.)

INDENTIFIED BY ‘(비밀번호)’ 는 사용자의 비밀번호를 설정합니다.

 

SHOW DATABASES;

데이터베이스들의 목록을 보여주는 명령어

 

USE (데이터베이스명)

(데이터베이스명)이라는 이름의 데이터베이스를 사용

 

DROP DATABASE (데이터베이스명);

(데이터베이스명)이라는 이름의 데이터베이스를 제거합니다.


CREATE TABLE (테이블명)(

_id INT PRIMARY KEY AUTO_INCREMENT,

name VARCHAR(32) NOT NULL,

job VARCHAR(64) DEFAULT ‘student’,

phone VARCHAR(12)

) ENGINE=INNODB;

(테이블명)이라는 이름을 가진 테이블을 생성합니다.

( ) 내부에 속성을 입력합니다. 각각에 대한 설명은 아래와 같습니다.

_id 란 이름의 칼럼을 추가하며, 데이터 타입은 INT 입니다. 해당 칼럼을 PRIMARY KEY(기본 키)로 설정합니다. AUTO_INCREMENT를 통해 자동으로 인덱스를 증가시킵니다.

name 이란 이름의 칼럼을 추가하며, NULL을 허락하지 않으므로 자료를 입력할 때 항상 값을 넣어줘야 합니다.

job 이란 이름의 칼럼을 추가하며, DEFAULT(아무런 값을 입력하지 않았을 때의 값) ‘student’로 설정합니다.

phone 이란 이름의 칼럼을 추가합니다.

ENGINE = INNODBMySQL의 저장구조를 설정합니다.(생략가능)

 

DESCRIBE (테이블명);

(테이블명)이라는 이라는 테이블의 구조를 확인합니다. 줄여서 DESC (테이블명); 또한 가능합니다.

 

-      참고

Field = 열 이름

Type = 해당 열의 자료형 ex) int(11) '11자리의 정수값을 저장할 수 있는 자료형'

Null = NULL 값을 허용할 것인지 아닌지를 나타내는 제약사항으로 YES로 지정하면 NULL 값을 허용

Key = 해당 열이 ''로 지정되어 있는지 나타냄.

Default = 그 열에 주어진 '기본값' , 생략했을 경우 적용되는 값

자료형

INTEGER = 정수값을 저장할 수 있는 자료형

CHAR = 문자열을 저장할 수 있는 자료형. 열의 최대 길이를 지정해야 함 => 고정 길이 문자열

VARCHAR = 문자열을 저장할 수 있는 자료형.데이터크기에 맞춰 저장공간의 크기도 변경됨 =>가변 길이 문자열

DATE = 날짜값을 저장할 수 있는 자료형. 연월일

TIME = 시간을 저장할 수 있는 자료형. 시분초

 

SHOW TABLES;

데이터베이스 안의 사용 가능한 테이블 목록을 보여주는 명령어

 

INSERT INTO (테이블명) (칼럼1, 칼럼2, … ) VALUES (칼럼1의 값, 칼럼2의 값, … );

(테이블명)이라는 테이블의 (칼럼1, 칼럼2, … ) 맞춰서 (칼럼1의 값, 칼럼2의 값, … )을 넣습니다.


SELECT (칼럼1, 칼럼2, … ) FROM (테이블명);

(테이블명) 이라는 테이블에서 (칼럼1, 칼럼2, … )의 값을 읽어옵니다.

 

SELECT * FROM (테이블명);

(테이블명) 이라는 테이블에서 (*: 모든)데이터를 읽어오는 명령어

 

-      참고

숫자로 구성된 데이터      =  수치형 데이터(오른쪽 정렬)

문자로 구성된 데이터      =  문자열형 데이터(왼쪽 정렬)

날짜와 시각을 나타내는 데이터 =  날짜시간형 데이터(왼쪽 정렬)

열은 하나의 자료형만 가질 수 있고, 수치형의 열에 문자형의 데이터를 저장할 수는 없다.

값이 없는 데이터 = NULL

 

SELECT * FROM (테이블명) ORDER BY (칼럼 명);

(테이블명) 이라는 테이블에서 (*: 모든)데이터를 읽어오는데, (칼럼 명)을 기준으로 정렬하여 읽어옵니다.

 

SELECT * FROM (테이블명) WHERE (조건);

(테이블명) 이라는 테이블에서 (*: 모든)데이터를 읽어오는데, (조건)을 만족하는 행을 읽어옵니다.

 

SELECT * FROM (테이블명) WHERE (칼럼 명) LIKE ‘2017%’;

(테이블명) 이라는 테이블에서 (*: 모든)데이터를 읽어오는데, (칼럼 명)에서 값이 2017로 시작하는 모든 값을 읽어옵니다.

 

SELECT * FROM (테이블명) WHERE (칼럼 1) <> (칼럼 2);

(테이블명) 이라는 테이블에서 (*: 모든)데이터를 읽어오는데, (칼럼 1) (칼럼 2)가 같지 않은 행만 읽어옵니다.

( <>!= 와 같은 의미 입니다.)

 

ALTER TABLE (테이블명) ~ ;

(테이블명)이라는 이름의 테이블을 대상으로 테이블의 이름을 변경(RENAME)하거나 테이블에 칼럼(속성)을 추가(ADD)하거나 테이블의 칼럼(속성)을 변경(CHANGE, MODIFY)하거나 테이블의 칼럼(속성)을 제거(DROP)하는 명령을 내릴 수 있습니다.

 

ALTER TABLE (테이블명) RENAME TO (바꿀 이름);

(테이블명)이라는 테이블의 이름을 (바꿀 이름)이라는 이름으로 바꿉니다.

 

ALTER TABLE (테이블명)

ADD COLUMN (새로운 속성) INT NOT NULL AFTER (기존의 속성_1),

ADD PRIMARY KEY (기존의 속성_2);

(테이블명)이라는 테이블에 (새로운 속성)이라는 이름의 속성을 (기존의 속성_1)의 뒤에 추가합니다.

이때 (새로운 속성) INT형 자료를 가지며 NULL을 허용하지 않습니다.(NOT NULL)

또한 (기존의 속성_2)PRIMARY KEY(기본 키)로 변경합니다.

 

ALTER TABLE (테이블명)

MODIFY COLUMN (속성 이름) (변경할 타입);

(테이블명)이라는 테이블의 (속성 이름)이라는 속성의 타입을 (변경할 타입)으로 바꿉니다.

 

ALER TABLE (테이블명)

CHANGE COLUMN (속성 이름) (변경할 속성 이름) (변경할 타입);

(테이블명)이라는 테이블의 (속성 이름)이라는 속성의 이름을 (변경할 속성 이름)으로 바꾸고 타입을 (변경할 타입)으로 바꿉니다.

 

ALTER TABLE (테이블명)

DROP COLUMN (속성 이름),

DROP PRIMARY KEY;

(테이블명)이라는 테이블에서 (속성 이름)이라는 이름의 속성을 제거합니다.

또한 PRIMARY KEY(기본 키)를 제거합니다.


UPDATE (테이블명)

SET (속성 이름) = (바꿀 값)

WHERE (조건: ex. Age > 20);

(테이블명)이라는 테이블에서 WHERE 구문의 조건에 맞는 레코드의 (속성 이름) 값을 (바꿀 값)으로 변경합니다.

- 참고

좌측의 테이블이 있다고 했을 때, 현재 adult 속성의 값을 보면 제대로 맞지 않습니다.

이를 수정하기 위해서 UPDATE 구문을 사용하겠습니다.

 

사용된 명령어는 아래와 같습니다.

UPDATE updateTest

SET adult = ‘Yes’ WHERE age > 19;

 

UPDATE updateTest

SET adult = ‘No’ WHERE age <= 19;

 

결과는 아래 사진과 같습니다.

 


DELETE FROM (테이블명) WHERE _id = 3;

(테이블명)이라는 이름의 테이블에서 _id = 3인 데이터를 삭제합니다.

WHERE 구문을 입력하지 않으면 테이블의 모든 데이터가 제거됩니다.

 

DROP TABLE (테이블명);

(테이블명)이라는 이름의 TABLE을 제거합니다. (DELETE는 데이터만 제거하는 것이고 DROP는 테이블 자체를 제거하는 것)

 

TRUNCATE TABLE (테이블명);

(테이블명)이라는 이름의 테이블의 모든 데이터를 삭제합니다.

 

           - 참고

           DELETE 명령은 데이터를 순차적으로 삭제합니다.

           TRUNCATE 명령은 테이블 자체를 삭제하고 같은 이름의 테이블을 새로 생성합니다.

           (테이블을 DROPCREATE 하는 명령어입니다.)

           따라서, 모든 데이터를 삭제할 때 DELETE 명령보다 TRUNCATE 명령이 처리속도가 빠르지만

TRUNCATE 명령은 데이터의 복구가 불가능합니다.


내용에 대한 피드백 및 궁금한 점은 댓글 및 이메일(doorbw@outlook.com) 으로 말씀해주세요 :)

다음 포스팅에서는 '조건에 따른 데이터 검색'에 대한 명령어를 알아보겠습니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요



안녕하세요. 문범우입니다.

오늘은 mongoDB의 database, collection, document 들에 대해서 알아보겠습니다.

기본적인 개념들은 지난 포스트를 참고해주시고, 오늘부터는 직접적으로 생성하고 제거하는 등의 활동을 해볼게요.



지난 포스트에서 알아본 듯이 mongoDB는 아래와 같은 architecture를 가지고 있습니다.


Database_1

Collection_1

Documents_1

 

“_id” : “~~~~~~~~~~~~”,

“name” : “홍길동”,

“age” : “30”,

. . .

 

Documents_2

. . .

 

Documents_3

. . .

. . .


 

Collection_2

. . .


Database의 내부에 Collection, 그리고 Collection 내부에 Document가 존재합니다.

이번 포스팅에서는 최종적으로 Documents 를 생성하여 우리가 원하는 key와 value를 저장해보도록 하겠습니다.

물론 그러기 위해서는 아래와 같은 과정이 필요합니다.


Database 생성 -> Collection 생성 -> Documents 생성


그리고 각각을 제거해보는 것까지 함께 해보도록 하겠습니다.


Database 생성-> Collection 생성 -> Documents 생성 -> Documents 제거 -> Collection 제거 -> Database 제거




1. Database 생성

먼저 mongoDB의 server를 키고, mongoDB에 들어갑니다.

그리고 show dbs 명령어를 통해 현재 만들어진 database를 확인할 수 있습니다.



위의 사진과 같이 아무것도 뜨지 않는다는 것은 내가 만든 데이터베이스가 없거나

만든 데이터베이스 내부에 한개 이상의 Document가 존재하지 않는다는 것 입니다.

즉, 데이터베이스가 만들어져 있더라도 해당 데이터베이스 내부에 Documents가 하나도 없다면 리스트에 보이지 않습니다.

이때, 자신이 사용중인 데이터베이스를 확인하기 위해서는 db 명령어를 입력합니다.


현재 저는 test라는 database를 사용하고 있네요.

이제 새롭게 database를 생성해보고 해당 database로 진행해보겠습니다.



use newDatabase 명령어를 통해 newDatabase라는 이름을 가진 database를 새롭게 만듭니다.

(이때 만약 해당 이름을 가진 데이터베이스가 존재한다면

새롭게 만들어지지 않고 기존에 있던 데이터베이스를 사용하게 됩니다.)

db 명령어를 통해서 사용중인 database가 바뀌었음을 확인할 수 있습니다.



2. Collection 생성

이번에는 collection을 생성해보겠습니다.

collection을 생성하기 위해서는 db.createCollection(name,[options]) 이라는 명령어를 사용합니다.

이때 name은 string Type으로써, collection의 이름을 말하며 options는 document Type으로써 선택적인 매개변수입니다.

공식문서를 통해 확인해보시고 필요한 항목을 사용하시면 됩니다. collection 이름은 firstCollection 으로 만들어보겠습니다.



지금까지 만들어진 collection을 확인하기 위해서는 show collections 명령어를 통해서 가능합니다.




3. Document 추가

Document 는 함수 자체에서 insert로 명시되어 있기에 '생성'이라는 말 대신 '추가'라는 말을 사용하였습니다.

새로운 Document를 추가하기 위해선 어떤 collection에 추가할지도 함께 고려해야합니다.

즉, 명령어에는 collection의 이름과 추가될 document의 내용이 들어갑니다.

db.COLLECTION.insert([{document1},{document2}, ... ]) 가 COLLECTION 이라는 이름을 가진 collection에 새로운 document를 추가하는 명령어 입니다.

해당 명령어를 통해 이름, 성별, 전공을 가진 document를 2개 추가해 보도록 하겠습니다.



그리고 db.COLLECTION.find() 을 통해 현재까지 추가된 document를 확인합니다.





4. document 제거

document를 제거하기 위해서는 db.COLLECTION.remove(<query>,<justOne>) 함수를 사용합니다.

db.COLLECTION.remove(<query>,<justOne>)에 대한 공식문서의 설명은 아래와 같습니다.



즉, query는 삭제할 document의 기준, 조건을 말합니다. 만약 query를 비워둔다면 모든 documents 가 해당되니 유의하세요.

justOne 은 한개만 지울 것인지에 대한 변수입니다.

default로 false값을 가지며, 딱 하나의 document만 지울때는 true로 설정하면 됩니다.


저는 3번에서 입력한 document 중 pika라는 이름을 가진 document 하나만 제거해보도록 하겠습니다.



document 하나가 올바르게 지워진 것을 알 수 있습니다.



5. Collection 삭제

현재 사용하고 있는 database의 collection을 보려면, show collections 라는 명령어를 사용하면 된다고 말하였습니다.

한번 더 확인해보겠습니다.


firstCollection 이라는 collection 하나만 존재하므로 하나를 더 생성합니다.



다시 secondCollection을 지워보도록 하겠습니다.

collection을 지우는 명령어는 db.COLLECTION.drop() 입니다.




6. Database 제거

현재 제가 만들어놓은 database의 항목을 확인해보기 위해 show dbs 명령어를 입력합니다.

제거할 database를 임시로 만들기 위하여 temp 라는 database를 만듭니다.



하지만 use temp 명령어를 입력하여도 temp라는 database는 하나이상의 document를 가지고 있지 않기 때문에

show dbs 에서 리스트에 보이지 않습니다. 따라서 빠르게 document를 추가해줍니다.

이때 따로 collection을 미리 생성하지 않아도 아래 명령어가 가능합니다.

db.tempCollection.insert({"name":"jone"})




이제 사용하지 않는 temp라는 database를 제거하기 위해 해당 database를

use DATABASE_NAME 을 통해 선택하고, db.dropDatabase() 함수를 사용하여 제거합니다.




이렇게


Database 생성-> Collection 생성 -> Documents 생성 -> Documents 제거 -> Collection 제거 -> Database 제거


순서대로 진행하였습니다.


마지막으로 각각에 대한 명령어를 정리해볼게요 !



정리


 

생 성 (추 가)

확 인

제 거 (삭 제)

Database

use DATABASE

show dbs

db.dropDatabase()

Collection

db.createCOLLECTION(name,[options])

show collections

db.COLLECTION.drop()

Document

db.COLLECTION.insert({do1},{do2}, …)

db.COLLECTION.find()

db.COLLECTION.remove(<query>,<justOne>)



오늘은 Database, Collection, Document 를 직접 생성하고 확인하고 제거해보았습니다.

다음엔 입력한 데이터를 이용한 실습을 진행해보겠습니다.

문의사항은 덧글이나 이메일(doorbw@outlook.com)을 이용해주세요 :)

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요

안녕하세요. 문범우입니다.

지난 시간에는 간단하게 MongoDB를 설치해보았습니다.

이번에는 앞으로 MongoDB를 다루기 위해 필요한 NoSQL에 대한 기초적인 개념 공부를 진행하고

윈도우에서 보다 쉽게 MongoDB를 사용하기 위해 환경변수 설정을 진행해보도록 할게요!





1. NoSQL

먼저 NoSQL에 대한 개념을 공부해보겠습니다.

NoSQL 데이터베이스는 전통적인 관계형 데이터베이스에 비해 덜 제한적인 일관성 모델을 이용하는 데이터의 저장 및 검색을 위한 매커니즘을 제공합니다.

NoSQL 시스템은 SQL 계열 쿼리 언어를 사용할 수 있다는 사실을 강조한다는 면에서 'Not only SQL'로 불리기도 합니다.

또한 관계형 데이터베이스가 아니므로 고정된 schema 또는 JOIN이 존재하지 않습니다.


2. Document Model

MongoDB 는 Relational Model 이 아닌 Document Model 입니다.

먼저 아래 사진을 확인해볼게요!


사진의 아래, Document Model을 확인하시면 각각의 데이터들이 Collection으로 묶인 것을 볼 수 있습니다.

MongoDB 에서는 각각의 데이터(RDMS에서는 레코드라고 하는 것)들이 Document 로써 존재합니다.

그리고 Document 들의 묶음을 MongoDB에서 Collection이라고 말합니다.

또한 Collection 들의 물리적인 컨테이너는 Database라고 하죠.


아래 사진을 보면 좀 더 이해가 가실 겁니다.



이해가 가시나요?

그럼 Document에 대해서 좀 더 알아보도록 하겠습니다.

위에서 언급했듯이 Document는 RDMS의 record와 비슷한 성격을 지닌 녀석입니다.

위 사진에서 볼 수 있듯이 하나의 Document 는 한개 이상의 key-value pair 로 이루어져 있습니다.

RDMS 에서 속성이라고 하는 것을 key라고 생각하시면 편할 것 같아요.

Document의 예를 확인해볼게요!




위의 사진을 확인하시면, _id, name, city, address, phone 라는 key를 확인하실 수 있으며 그에 대응하는 value를 확인 할 수 있습니다.

즉, 위의 Document는 총 5개의 key-value pair를 가지고 있습니다.

위의 key 중에 _id 는 12bytes 의 hexadecimal 값으로서, 각 document의 유일성을 보장합니다.

_id에 관해, 각 byte 별로 의미하는 것은 다음과 같습니다.

첫 4bytes: 현재 timestamp / 다음 3bytes: machine id / 다음 2bytes: MongoDB 서버의 프로세스 id / 마지막 3bytes: 순차번호


Document는 dynamic schema를 갖고있습니다. 같은 collection 안에 있는 document 끼리 다른 schema를 가질 수 있다는 것인데 쉽게 말해서 서로 다른 key들을 가지고 있을 수 있다라고 생각하시면 됩니다.


3.Data Modeling

간단한 데이터 모델링을 참고해보도록 할게요.

블로그를 생각해 봅시다.

블로그에서는 다수의 게시글이 존재하죠? 그리고 각 게시글은 여러개의 태그를 가질 수 있고, 각 게시글에는 여러개의 댓글을 가질 수 있습니다.

만약 RDMS에서 해당 데이터베이스를 간단히 디자인한다면 아래와 같은 3개의 테이블을 만들 것 입니다.


 Comment

Post

Tag 

*id 

*id 

*id 

Post_id 

title 

Post_id 

username 

content 

tagContent 

content 

username 

 

 time

time 

 


그리고 Comment와 Tag 테이블은 Post 테이블에 속하도록 디자인되겠죠.

하지만 NoSQL 에서는 이 모든 것을 하나의 Document 에 넣습니다. 아래와 같이 디자인 될 것 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
 _id: POST_ID,
 title: POST_TITLE,
 content: POST_CONTENT,
 username: POST_WRITER,
 tags: [ TAG1, TAG2, TAG3 ],
 time: POST_TIME
 comments: [
 { 
 username: COMMENT_WRITER,
 mesage: COMMENT_MESSAGE,
 time: COMMENT_TIME
 },
 { 
 username: COMMENT_WRITER,
 mesage: COMMENT_MESSAGE,
 time: COMMENT_TIME
 }
 ]
}
cs


RDMS 와 NoSQL의 차이에 대해서 대략적으로 이해가 가셨나요?

추가적인 사항은 댓글을 남겨주시거나 doorBW@outlook.com 으로 메일 주세요 :)


4. MongoDB 환경변수 설정(Windows)

마지막으로 MongoDB를 좀 더 편리하게 사용하기 위해 환경변수 설정을 하도록 하겠습니다.

환경변수 설정을 통해 매번 MongoDB의 설치 경로로 이동하실 필요가 없으실 거에요.

아래 사진의 순서대로 진행하시면 됩니다.


1. 제어판 -> 시스템 및 보안 -> 시스템 -> 시스템 보호



2. 시스템 속성 창에서 환경변수 클릭



3. 변수이름 Path 를 누르고 편집 클릭




4. 새로만들기 -> MangoDB 설치경로 입력 -> 확인 클릭




이렇게 설정하시면 됩니다!

이제 확인해볼까요?




네, 정상적으로 됩니다 :)


추가적으로 데이터베이스 디텍토리를 변경하고 싶으시다면 아래 명령어를 입력하시면 됩니다.


C:\Program Files\MongoDB\Server\3.2\bin> mongod --dbpath "원하는 디텍토리"


이상으로 MongoDB 환경변수 설정을 마무리하겠습니다.


오늘 NoSQL개념 3가지와 MongoDB 환경변수 설정을 진행하였습니다.

다음 포스팅에서는 본격적으로 database를 만들고 삭제하는 등의 진행을 해볼게요 :)

문의사항은 덧글 및 이메일(doorbw@outlook.com)을 이용해주세요.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요