지난 1편 포스트에 이어서 조건 조합하기에 대해 알아보자
<조건 조합하기>
AND로 조합하기
만약 a라는 열과 b라는 열이 있다고 했을 때 2개의 열의 행이 0이 아닌 경우를 검색한다고 해보자!
그런데 왜 AND를 써야할까?
만약 조건을 1개만 걸어서 검색하게되면 수천만건의 행들이 튀어나올 수 있기 때문에 처리하는데 비용이 많이 발생한다.
그래서 보통 2개이상의 조건을 걸어서 범위를 좁혀줘서 원하는 값을 보다 빠르고 정확하게 뽑아내기 위함이다.
이전에 공부했던 <> 연산자를 통해서 2개의 열에서 0이나니 값만 추출해보자
SELECT * FROM 테이블명 WHERE a<>0 AND b<>0;
이렇게 작성해주면 조건식이 현재 a라는 열과 b라는 열의 행중에 0이 아닌 것들만 뽑히게 된다.
AND연산자는 논리곱을 계산하는 논리연산자이다. 벤다이어그램을 그려본다고 가정했을 때
이들 집합이 겹치는 부분 즉 ‘교집합’으로 계산할 수 있다.
결국 AND연산자는 논리곱을 계산하는 논리 연산자이다.
OR로 조합하기
어느쪽이든 하나만 참이 되면 조건식은 참이 된다 라고 할 경우에 사용할 수 있는 것이 바로 OR조건이다.
OR또한 논리 연산자의 하나로 좌우 항목이 모두 필요한 이항연산자이다.
AND와 달리 어느 쪽이든 조건을 만족하면 그 결과는 참이 된다.
모든 조건이 거짓인 경우 결과는 거짓이 된다.
즉 OR는 '또는'에 해당한다.
그럼 조건식을 예시로 한번 알아보자
a열이 0이 아니거나 b열이 0이 아닌 행을 검색하려면 어떻게 해야할까?
SELECT * FROM 테이블명 WHERE a<>0 OR b<>0;
이렇게 작성해주면 된다.
OR 연산자는 조건을 만족하는 행을 집합으로 표현했을 때, 이 집합들을 합한 부분, 즉 '합집합'으로 계산할 수 있다.
OR연산자는 논리합을 계산하는 논리연산자이다.
*POINT -> OR로 조건식을 연결하면 어느 쪽이든 조건을 만족하는 행을 모두 검색할 수 있다.
AND와 OR를 사용할 경우 주의할 점
만약에 no라는 열의 값이 1 또는 2인 행을 추출하고 싶을 경우 다음과 같이 작성해 줄 수 있다.
SELECT * FROM 테이블명 WHERE no=1 OR 2;
이렇게 작성하면 상수'2'는 논리 연산으로 항상 참이 되기 때문에 결과적으로 모든 행을 반환하게 된다.
올바른 조건식이 아니다 올바른 조건식을 작성해보자
SELECT * FROM 테이블명 WHERE no=1 OR no=2;
이렇게 작성해줘야 원하는 값을 뽑을 수 있다.
AND와 OR를 조합해 사용하기
만약 조건식을 a라는 열은 0이 아니다 a<>0 <- 이렇게 던졌다고 해보자.
0, 1, 2라는 3개의 값이 존재한다고 가정해보면
a<>0 이라는 조건은 1또는 2의 경우 참이 된다.
~이 아닌 이라는 조건 보다는 ~인 이라는 조건이 더 이해하기 쉬울 것 같다.
ex) 0이 아닌것을~ 구해줘 ! 보다는 1, 2인 값을 구해줘! 가 훨씬 이해하기 쉽다는 뜻이다.
그러므로 a<>0을 a=1 OR a=2 라는 조건으로 바꿔보자
SELECT * FROM 테이블명 WHERE a=1 OR a=2 AND b=1 OR b=2; 라고 작성하면
a열이 1 또는 2이고, b열이 1또는 2인 행을 검색하겠다는 뜻이다.
그러니까 쉽게말해 a라는 열과 b라는 열을 들고와서 1이랑 2가 포함된 행을 뽑아서 보여줘! 라는 뜻이 된다.
기존에 작성된 a<>0 AND b<>0이라는 조건식을 a=1 OR a=2 AND b=1 OR b=2 로 변경했는데
결과물을 보면 a<>0 AND b<>0이라는 조건식과는 다르게 나오게 된다.
그 이유가 무엇일까?
- 연산자의 우선순위
결과가 다른 이유는 AND와 OR의 우선순위가 다르기 때문이다.
OR보다는 AND쪽이 우선순위가 높기 때문이다. a=2 AND b=1 이 먼저 계산된다.
보기 쉽게 괄호로 나타내면
WHERE a=1 OR (a=2 AND b=1) OR b=2
즉 3개의 조건식이 OR로 연결된 것과 같아진다.
따라서 조건식은 다음과 같이 3개로 나뉘게 된다.
a =1
a= 2 AND b=1
b=2
내가 원했던 조건은
a열이 1또는 2이며
b열이 1또는 2인 행을 뽑아줘!
였지만
a열이 1이다 또는 a열이 2이며 b열이1이다 또는 b열이 2이다
라는 엉뚱한 조건이 되어버렸다.
처음에 원했던 조건으로 데이터를 뽑아내려면 괄호를 다르게 줘야한다.
즉 괄호로 내가 원하는 우선순위를 지정해야한다는 것이다.
SELECT * FROM 테이블명 WHERE (a=1 OR a=2) AND (b=1 OR b=2);
이렇게 작성해줘야한다.
조건이 길어질수록 잘못된 조건이 부여될 수 있으니 처음부터 괄호로 조건을 묶어두는 습관을 잘 만드는 것이 중요하겠다.
*POINT -> AND는 OR에 비해 우선 순위가 높다!
NOT으로 조합
이제 또 다른 논리 연산자인 NOT에 관해 알아보자
이전에는 이항연산자로 왼쪽값과 오른쪽값에 모두 해당하는 논리연산자를 배워봤는데
이번에 작성하는 NOT 논리연산자는 오른쪽에만 해당되는 '단항 연산자'이다.
예를 들어서
SELECT * FROM 테이블명 WHERE NOT (a<>0 OR b<>0); 이라고 작성했다면
a가 0이거나 b가 0인 값을 뽑아줘에서 NOT연산자로 인해서 둘 중 하나가 아니라
둘다 뽑아줘! 라고 바뀌게된다.
그래서 결국 a와 b열의 값이 0인 행을 찾아서 보여주게 되는 것이다.
<패턴 매칭에 의한 검색>
LIKE로 패턴 매칭하기
= 연산자로 검색할 경우 열 값이 완전히 일치 할 때 참이 된다.
LIKE술어를 사용하게되면 열 값이 부분적으로 일치하는 경우에도 참이 된다.
열명 LIKE '패턴'
LIKE술어는 이항 연산자 처럼 항목을 지정한다. 왼쪽에는 매칭 대상을 지정하고 오른쪽에는 패턴을 문자열로 지정한다.
단, 수치형 상수는 지정 할 수 없다. 패턴을 정의할 때는 다음과 같은 메타문자를 사용할 수 있다.
%_
'와일드카드'라고도 불리는 메타문자는 패턴 매칭 시 '임의의 문자 또는 문자열'에 매치하는 부분을 지정하기 위해 쓰이는
특수 문자이다. 퍼센트(%)는 임의의 문자열을 의미하며, 언더스코어(_)는 임의의 문자 하나를 의미한다. 패턴을 정의할 때는
메타문자를 여러개 사용할 수 있다.
LIKE 뒤에 *을 사용할 수는 없다. LIKE를 써서 특정한 임의의 데이터를 뽑고 안뽑고는 정할 수 있지만
완전 일치가 되지 않는 이상의미가 없는데 *을 쓰게되면 완전일치가 존재할 수 없게되어 사용이 불가능한 것이다.
예를 들어 00게시판이라는 값을 카테고리 데이터에서 출력하고 싶다면
SELECT * FROM 테이블명 WHERE category LIKE '%게시판' 이라고 작성해주면 된다.
만약 앞뒤도 모두 임의의 문자로 넣어주고 중간값만 일치하면 뽑아내게 하고 싶다면?
SELECT category FROM 테이블명 WHERE category LIKE '%게시%';
이렇게 작성해주게되면 해당 테이블명에 존재하는 컬럼중에 카테고리안에서 앞뒤 사이에 중간문자열이 '게시'가 포함된
모든 데이터를 출력해준다.
SELECT category FROM 테이블명 WHERE category LIKE '%'; 또한 이렇게 작성해줘도 문제는 없다.
해당 카테고리안으로 들어가서 어떤 문자든 상관없이 모두 뽑아내는 것이다.
* POINT -> %는 임의의문자열 뿐만 아니라, 빈 문자열에도 매치한다 결국 %위치에 값이 없더라도 매칭이된다는 것이다.
전방일치 : '문자열%'
중간일치 : '%문자열%'
후방일치 : '%문자열'
이렇게 3가지로 정리가된다.
LIKE로 패턴 매칭하기
그런데 만약 데이터에서 메타문자 %가 아닌 일반문자 %를 구해야 할 경우에는 어떻게 해야할까?
그럴때는 이스케이프를 통해서 데이터를 조회할 수 있다.
예를 들어 LIKE에서는 메타문자 %와_를 사용할 수 있다 <- 이런 문장이 들어간 값을 뽑아내려고할 때
%는 메타문자와 동일하게 인식될 우려가 있으니 이럴 때 이스케이프를 쳐주면되는데
SELECT * FROM 테이블명 WHERE 필드명 LIKE '%\%%'; 이렇게 작성해주면?
맨 앞에 붙은 %는 메타문자의 %이다. 임의의 문자열과 매칭된다. 그 다음에 나오는 %는 앞에 \가 있어서
이스케이프 된 것을 의미하기 때문에 임의의 메타문자가 아닌 일반문자 %를 의미한다.
그럼 지금 총 3개의 %가 있는데
위에 빨간 예시 문장을 기준으로 설명하면
첫번째 % : 메타문자
두번째 \% : 일반문자
세번째 % : 메타문자
이렇게 정리 할 수 있다.
이것은 %에만 해당하는 것이 아니라 _ 언더스코어도 마찬가지로 메타문자가 아닌 일반문자를 뽑을 때
동일하게 앞에 이스케이프 \ 를 붙여주면 된다.
ex) '_\__
총 3개의 언더스코어중에 첫번째는 메타문자 두번째는 \가 앞에서 이스케이프 시켜서 일반문자
마지막은 역시 메타문자가 되는 것이다.
문자열 상수 '의 이스케이프
메타문자를 검색할 때 처럼 문자열 상수를 검색할 때도 같은 문제가 발생한다.
문자열 상수는 '문자열'과 같이 '로 둘러싸 표기한다.
표준SQL에서는 이를 해결하기 위해서 '를 2개 연속해서 붙여 쓰는 것으로 이스케이프 처리를 한다.
예를 들어 문자열이 It's라고 했을 때 해당 문자열에는 ' 가 문자사이에 들어가서 혼란을 줄 수 있다.
이를 해결하기 위해서 'It''s' 라고 쓰면된다.
이렇게되면 SQL은 '' 2개를 하나의 문자열 ' 로 인식할 수 있게 된다.
또한 만약 데이터가 '하나의 문자만 가지고있고 이것을 조회하고 싶다면 '문자열' 이 공식이니까 내가 꺼내야 할 ' 라는 문자를 넣기위해서
'에 1개를 더 붙여서 연속으로 사용해서 '' 라고 표기하게 되니까 결국 '''' 이렇게 총 4개를 작성하는 것이다.
4개중에 제일 앞에 있는 ' 와 제일 뒤에있는 ' 는 문자열을 감싸주는 것이고 그 사이에 '' 2개는 1개의 '를 뽑아내기 위해서
구분을 주려고 ''를 붙여준 것을 알고있어야 한다.
이렇게 간단한 경우에는 직접 LIKE를 통해 매칭하면되지만 더 복잡한 패턴을 매칭해야 할 경우에는
정규 표현식(Regular Expression)을 사용하는 편이 낫다.
최근에는 대부분의 데이터베이스가 정규 표현식을 지원한다. 정규 표현식에서 더 많은 메타문자를 사용해서 폭넓게 패턴을 지정할 수 있다.
글이 길어져서 3편으로 이어서 작성해야겠다! 3편부터는 정렬 ORDER BY에 대해서 알아도록 하자!
여기까지 읽고 공부하고있는 그대가 있다면 박수를 보내오..
모든 포스팅에 대한 내용은 도서 SQL첫걸음에서 익히고 배운 것들에 대한 내용을 직접 타이핑 하였음을 밝힙니다.
'BackEnd' 카테고리의 다른 글
SQL 데이터베이스에 대해 제대로 알자(4) - 수치연산, CASE (0) | 2023.03.09 |
---|---|
SQL 데이터베이스에 대해 제대로 알자(3) - ORDER BY, LIMIT (0) | 2023.03.08 |
SQL 데이터베이스에 대해 제대로 알자(1) - 데이터베이스란? (0) | 2023.03.08 |
접근제어자(Access Modifier) 무조건 이해하기 (0) | 2023.02.13 |
JVM은 무엇일까? 자바 코드는 어떻게 실행될까? (0) | 2023.01.31 |