SELECT | 기본

Introduce

본 문서는 2022년 3월 18일 에 작성되었습니다.

순서로는 Velog -Unchaptered / Snytax | TCL Syntax 이후지만,
작성 시점으로는 Velog - Unchaptered / SELECT | 관계형 대수 이후에 작성되었습니다.

여기서는 SELECT 에서 내가 원하는 정보를 조회하기 위해서 필요한 다양한 명령어 및 단일함수를 알아볼 생각입니다.

단, 이러한 기능을 사용하기 위해서는 다양한 연산자에 대한 기본적 지식 이 필요합니다.


Thoery

SQL 비교 연산자

=,>,>=,<,<==, >, >=, <, <=

SQL 고유 연산자

BETWEEN a AND b
IN (a,b,c)
LIKE '비교문자열'
IS NULL
IS NOT NULL

LIKE 를 이용한 비교에는 와일드 카드를 사용할 수 있다.

% 는 해당 방향으로 어떤 문자든 1개 이상 있는 경우
_ 는 해당 방향으로 어떤 문자든 1개만 있는 경우

SQL 고유 연산자

AND
OR
NOT

실행은 NOT , AND , OR 순서로 된다.

SQL 부정 연산자

!=,<>,!=!=, <>, !=

SQL 에서 부정 연산자를 사용해 비교할 경우,
인덱스를 사용하지 못하는 관계로 성능 저하가 발생한다.

따라서 이러한 경우,
관계형 대수 중 MINUS 명령어를 사용할 수도 있다.


SELECT Syntax

다양한 명령어를 SELECT 를 기준으로 공부했습니다.

SELECT 에서 복잡한 SQL 문을 작성할 수 있다면,
UPDATE, DELETE 에서는 손쉽게 사용할 수 있을 것입니다.
많은 기능이 SELECT 에서의 데이터 결합 등에 이용되기 때문 ...

단, 설명에 앞서 몇 가지 기본적인 문법을 소개하려 합니다.

* 연산자

해당 연산자는 테이블의 모든 칼럼을 지정해줍니다.

SELECT * FROM 테이블명;

as 연산자

해당 연산자는 테이블의 특정 칼럼명에 가명을 지어줍니다.

SELECT
   user_id as '아이디',
   user_email as '이메일'
FROM user;

DUAL 테이블

Oracle 에는 DUAL 테이블이 존재합니다.
이 테이블은 하나의 칼럼만 가지고 있으며, 모든 DB 계정에서 접근 가능합니다.

특정한 키워드, 명령어, 수식 등의 값을 확인 하거나
테이블 없이 출력값을 확인 하는 등에 활용할 수 있습니다.

SELECT sysdate FROM DUAL;

ROWNUM 예약어

Oracle 에는 ROWNUM 이라는 예약어가 존재합니다.
이 예약어는 자료형 SERIAL 처럼 출력 시 1부터 +1 씩 상승하는 일련번호를 붙여줍니다.

SELECT
   ROWNUM as '일련번호',
   user_id as '아이디',
   user_email as '이메일'
FROM user;

SELECT Basic

본 ## SELECT Basic 에서는
WHERE, GROUP BY, HAVING, ORDER BY 를 다룰 예정입니다.

SELECT * FROM 테이블명
WHERE 조건식
GROUP BY 기준 칼럼
HAVING 조건식
ORDER BY 기준 칼럼 정렬 방식;

쿼리문 실행 시, 적용 순서에 따라서 작성해보았습니다.

WHERE 절

DML 실행 시, 영향을 주는 로우(행)을 제한 하기 위해 사용합니다.

-- 사용방법 1 : 유저 존재 확인
SELECT * FROM user
WHERE user_name = 'unchaptered';

-- 사용방법 2 : 유저 재산 확인
SELECT * FROM user
WHERE user_money BETWEEN 100 AND 1000;

-- 사용방법 3 : 백수 혹은 프리랜서인 유저만 확인
SELECT * FROM user
WHERE user_jobs IN ('백수', '프리랜서');

-- 사용방법 4 : 일정 문자열을 포함하는 유저명 탐색
SELECT * FROM user
WHERE user_name LIKE '%chap%';

GROUP BY 절

DML 실행 시, 필터링 완료된 집합의 지정된 칼럼의 중복을 모두 제거 하기 위해 사용합니다.

SELECT * FROM user
GROUP BY 칼럼명;

# GROUP BY 사용 예시

user

user_numuser_iduser_name
1[email protected]unchaptered
2[email protected]helloMyName

post

post_numpost_titlepost_owner
1첫 게시글1
2두 게시글1
3세 게시글1
4첫 게시글2

post 테이블에서 user 별로 작성한 게시글 수를 알고 싶다고 하자.

SELECT
   post_owner as '작성자',
   COUNT(*) as '수량'
FROM user
GROUP BY post_owner;
작성자수량
13
21

아직은 배우지 않았지만, JOIN 을 사용해서 데이터를 확인해보면 다음과 같다.

작성자수량
unchaptered3
helloMyName1

HAVING 절

DML 실행 시, 필터링 완료된 집합의 특정한 조건을 만족하는 값 을 찾기 위해 사용합니다.

SELECT * FROM user
HAVING user_name = 'unchaptered';

기능적으로는 완벽하게 동일하지만, WHERE 과는 발생시점이 다르다.

ORDER BY 절 + 주의사항

DML 실행 시, 최종적으로 출력될 집합의 순서를 정렬하기 위해 사용됩니다.

SQL 문장 전체에서 1번만 사용할 수 있습니다.

-- 정렬 기본값은 ASC(오름차순), 적지않을 시 기본값 적용
SELECT * FROM user
ORDER BY 칼럼명;

-- DESC(내림차순) 도 가능
SELECT * FROM user
ORDER BY 칼럼명 DESC;

-- 복합 정렬도 가능
SELECT * FROM user
ORDER BY 칼럼명 DESC, 칼럼명 ASC, 칼럼면 DESC;

# 주의사항

최대 재산을 가진 유저 10명을 찾기 위해서 ORDER BY 를 사용하는 경우,
일반적으로 아래와 같은 SQL 문을 사용할 수 있다.

SELECT * FROM user
WHERE ROWNUM <= 10
ORDER BY user_money DESC;

하지만 SQL 문의 실행 시점을 고려해보면 WHERE 이 먼저 실행되어
10개로 필터링 된 정보가 재산을 기준으로 내림차순 됨을 예상 가능하다.

즉, 무작위 10 명의 재산 순위일 뿐인 것이다.

따라서 다음과 같이 후술할 서브쿼리 를 이용하여야 한다.

SELECT * FROM (
   SELECT * FROM user
   ORDER BY user_money DESC
) WHERE ROWNUM <= 10;

SQL 은 괄호 안의 서브 쿼리를 먼저 실행하는 특징이 있으므로,
n 개의 user 정보가 재산 내역으로 정렬되고 상위 10개만 출력된다.

LIMIT 절 + 성능 최적화

DML 실행 시,
정렬까지 완료된 결과 집합에 출력 수를 제한하는 것이다.

SELECT * FROM user
LIMIT 10;

# 성능 최적화

개인적인 생각으로는
WHERE 절 + ROWNUM 을 사용하면 데이터를 읽는 단계에서 10개로 제한이 되기때문에, 훨씬 효율적이지 않나라고 생각한다.

따라서 동일한 경우라면 LIMIT 보다 ROWNUM 을 사용하는 것이 옳다고 생각하는데, ... 실제로 현업에서는 어떻게 적용되는지 모르겠다.

해당 부분을 구글링해보니, LIMIT 의 성능 최적화 관련된 게시글 을 찾을 수 있었다.

해당 포스트에서는 두 가지 시나리오를 고려했다.

  1. 순차적으로 조회할 경우
  2. 한꺼번에 500만 번째 게시글을 조회할 경우

1번의 경우는 쉬웠지만, 2번의 경우는 커버링 인덱스 라는 방법을 권고해주었다.
커버링 인덱스는 쉽게 말하면, 자주 사용할 값들을 복합 PK 로 사용하고 SELECT 시 복합 PK 안에 있는 값들만 출력하려고 할 시, 커버링 인덱스 를 사용하여 성능 최적화가 이루어진다는 의미였다.

또한 저자는 의문을 가지는 시나리오로 네이버 쇼핑몰을 가지고 있었는데,
댓글에는 HBase 라는 것을 사용헀을 것 이라는 코멘트가 달려있었다.
HBase 는 NoSQL DBMS 중 일부로, 대규모 데이터 처리에 최적화 되어있다 라는 간단한 내용만 짚고 넘어가야겠다.

좋은 웹페이지 즐겨찾기