Post

Select에 대해

IN

IN

  • v IN (v1, v2, v3 ….) 에서 v 가 (v1, v2, v3 …) 중에 하나라도 값이 같다면 TRUE를 return 한다.

  • (v1, v2, v3 …) 는 명시적인 값이 될 수도 있고, subquery의 결과 (set or multiset)일 수도 있다.

NOT IN

  • v NOT IN (v1, v2, v3 ….) 의 모든 값과 값이 다르면 TRUE를 return 한다.
select * from member m where m.id in (2, 10); 
# 멤버의 아이디가 2 or 10인 값 return

unqualified attribute

unqualified attribute란 앞에 어떤 테이블의 attribute인지 명시하지 않은 attribute를 뜻 한다.

이러한 attribute의 경우 서브쿼리로 사용 시 어떤 table의 attribute인지 알 수 없다. 이러한 경우 mysql에서는 해당 attribute에서 가장 가까운 table을 참조한다고 알아두자.

EXISTS

EXISTS

  • subquery의 결과가 최소 하나의 tuple이라도 있다면 TRUE를 return한다.

NOT EXISTS

  • subquery의 결과가 단 하나의 tuple도 없다면 TRUE를 return 한다.

correlated query

subquery가 바깥쪽 query의 attribute를 참조할 때 그 subquery를 correlated subquery라고 부른다.

INEXISTS는 서로 바꿔가며 사용가능하다. 둘의 성능 차이가 거의 없다.

ANY

ANY

  • v 비교연산자 ANY (subquery) : subquery가 반환한 결과들 중 단 하나라도 v와의 비교 연산이 TRUE라면 TRUE를 return 한다.

SOME과 ANY는 같은 역할을 한다.

ALL

ALL

  • v 비교연산자 ALL (subquery) : subquery가 반환한 결과들과 v와의 비교 연산이 모두 TRUE라면 TRUE를 return 한다.

NULL

IS

IS는 NULL과 비교하기 위한 연산자이다.

UNKNOWN

UNKNOWN은 SQL에서 NULL과 비교 연산을 하게 될 때 나오는 결과이다. TRUE 일 수도 있고, FALSE 일 수도 있다 라는 의미다.

three-valued logic

  • 비교/논리 연산의 결과로 TRUE, FALSE, UNKNOWN을 가진다는 의미이다.

NULL과 비교연산 시

https://github.com/sunjong0214/algorithm-study/assets/117134728/0613d60c-8c35-42d0-a06c-d4340577146a

위 그림과 같이 결과가 나온다.

image

논리연산 시 UNKNOWN이 포함되었을 때 위와 같은 결과가 나온다는 것을 유의하자.

위의 연산 결과를 유의하지 않는다면 쿼리 작성 시 예상하던 값과 다른 값이 나올 수 있다.

대표적으로 where절에서 문제가 발생할 수 있다.

WHERE절의 condition

  • where절에 있는 condition의 결과가 TRUE인 tuple만 선택된다.
  • 즉, 결과가 FALSE 이거나 UNKNOWN인 tuple은 선택되지 않는다.

이런 특성 때문에 UNKNOWN에 대해 명심해야된다.

예제를 통해 살펴보자.

NOT IN 사용 시

v NOT IN (v1, v2, v3) 을 풀어서 서술한다면 다음과 같다.

v != v1 AND v != v2 AND v != v2

이때 v1, v2, v3 중 하나가 NULL이라면 어떻게 될까?

image

위와 같은 결과가 나오기 때문에 3 not in (1, 2, NULL)에서 예상하던 결과랑 다른 결과가 나오고 만다.

이런 문제를 잘 유의하며 쿼리를 작성해야한다.

JOIN

implicit join

  • from 절에는 table들만 나열하고 where 절에 join condition을 명시하는 방
  • old-style join syntax
  • where 절에 selection condition과 join condition 이 같이 있어 가독성이 떨어짐
  • 복잡한 join 쿼리를 작성하다보면 실수를 유발

explicit join

  • from 절에 JOIN 키워드와 함께 joined table들을 명시하는 방식
  • from 절에서 ON 뒤에서 join condition을 명시한다.
  • 가독성이 좋음
  • 복잡한 join 쿼리 작성시 실수할 가능성이 적음

inner join

  • INNER JOIN table ON v = v1과 같은 식으로 사용한다. 앞에 INNER는 생략 가능

  • 두 table에서 join condition을 만족하는 tuple들로 result table을 만드는 join

  • join condition에 =, <, >, != 등 여러 비교연산자 사용 가능

  • join condition에서 null 값을 가지는 tuple은 result에 포함 X

    image

outer join

  • 두 table 에서 join condition을 만족하지 않는 tuple들도 result table에 포함하는 join

  • LEFT, RIGHT, FULL 3 종류가 있다.
  • join condition에 =, <, >, != 등 여러 비교연산자 사용 가능

LEFT JOIN

  • from 절의 왼쪽 테이블에 있는 join condition에 매칭되지 않는 tuple들까지도 result table에 포함시킨다.

image

RIGHT JOIN

  • from 절의 오른쪽 테이블에 있는 join condition에 매칭되지 않는 tuple들까지도 result table에 포함시킨다.

image

FULL JOIN

  • mysql에서는 FULL OUTER JOIN은 지원하지 않지만 다른 sql에서는 지원
  • from 절의 모든 테이블에 있는 join condition에 매칭되지 않는 tuple들까지도 result table에 포함시킨다.

image

equi join

  • join condition에서 = (equality comparator)를 사용하는 join
    • equi는 inner join에서 =를 사용한 경우에만 equi join으로 보는 시각inner, outer 상관없이 =를 사용한 join이라면 equi join으로 보는 시각이 있다.

USING

  • 두 테이블에 같은 이름을 가지는 attribute를 equi join 시 사용할 수 있다.

  • 이때 해당 attribute는 result table에 한번만 표시된다.

  • ex)

    # USING 사용 전
    select * from employee E INNER JOIN department D ON E.dept_id = D.dept_i 
    #-------------------------------------------------------------------------
    # USING 사용 후
    select * from employee E INNER JOIN department D USING (dept_id);
    

USING 사용 전

image

USING 사용 후

image

natural join

  • 두 table에서 같은 이름을 가지는 모든 attribute pair에 대해서 equi join을 수행한다.
  • join condition을 따로 명시하지 않음

image

  • 같은 이름을 가진 attribute의 경우 USING과 같이 앞으로 나오게 된다.

  • 같은 이름을 가지는 모든 attribute pair에 대해 equi join을 수행하기 때문에 그 부분을 유의하자.

cross join

  • 두 table 의 tuple pair로 만들 수 있는 모든 조합을 result table에 포함

  • join condition이 없다.

  • implicit cross join : FROM table1, table2

    explicit cross join : FROM table1 CROSS JOIN table2

    둘 다 같은 의미

image

  • 위와 같이 두 table의 모든 tuple들이 서로 매칭된 결과가 나온다.
  • cross join @ MySQL
    • MySQL에서는 cross join = inner join = join 이다.
    • CROSS JOIN에 ON(or USING)을 같이 쓰면 inner join으로 동작
    • INNER JOIN (or JOIN)이 ON(or USING) 없이 사용되면 cross join으로 동작

ORDER BY

  • 조회 결과를 특정 attribute 기준으로 정렬해 가져오고 싶을 때 사용
  • default는 오름차순
  • 오름차순 : ASC
  • 내림차순 : DESC

만약 두개 이상의 attribute들을 정렬하고 싶을 땐 다음과 같이 작성하면 된다.

image

이때 ORDER의 순서는 앞에 dept_id를 기준으로 정렬 후 salary를 기준으로 정렬하게 된다. NULL의 경우엔 제일 앞에 정렬된다.

aggregate function

  • 여러 tuple들의 정보를 요약해서 하나의 값으로 추출하는 함수
  • 대표적으로 COUNT, SUM, MAX, MIN, AVG 함수가 있다.
  • (주로) 관심있는 attribute에 사용된다.
  • NULL 값들은 제외하고 요약 값을 추출한다.

ex) 임직원 수를 알고 싶을 때의 예제 (result = 16)

SELECT COUNT(*) FROM employee; 
# 결과 : 16
#########################################
SELECT COUNT(position) FROM employee;
# 결과 : 16
#########################################
SELECT COUNT(dept_id) FROM employee;
# 결과 : 14

(*)을 사용할 경우 모든 tuple들에 대해 count한 결과가 나오고, position도 같은 값이 나온다.

하지만 dept_id의 경우 tuple의 갯수인 16이 아니라 14가 나왔다.

그 이유는 dept_id에는NULL 값이 포함되어 있기 때문이다. 이렇듯 NULL 값을 제외하고 값을 구하기 때문에 웬만하면 (*)를 사용하자.

GROUP BY

  • 관심있는 attribute 기준으로 그룹을 나눠서 그룹별로 aggregate function을 적용시킬 때 사용
  • grouping attribute : 그룹을 나누는 기준이 되는 attribute
  • grouping attribute에 NULL 값이 있을 때는 NULL 값을 가지는 tuple끼리 묶인다.

ex)

SELECT CONUT(*), MAX(salary), MIN(salary), AVG(salary)
FROM works_on W JOIN employee E ON W.empl_id = E.id
WHERE W.proj_id = 2002;

image

GROUP BY 사용해 그룹별 조사

SELECT W.proj_id, CONUT(*), MAX(salary), MIN(salary), AVG(salary)
FROM works_on W JOIN employee E ON W.empl_id = E.id
GROUP BY W.proj_id;

image

  • SELECT 문에 GROUP BY에 있는 attribute를 적어줘야한다.

having

  • GROUP BY와 함꼐 사용함
  • aggregate function의 결과값을 바탕으로 그룹을 필터링하고 싶을 때 사용
  • HAVING 절에 명시된 조건을 만족하는 그룹만 결과에 포함

ex)

SELECT W.proj_id, CONUT(*), MAX(salary), MIN(salary), AVG(salary)
FROM works_on W JOIN employee E ON W.empl_id = E.id
GROUP BY W.proj_id
HAVING COUNT(*) >= 7;

COUNT의 결과값이 7 이상인 그룹만 가져온다.

SELECT 실행 순서

image

출처)

(1부) SQL로 데이터 조회하기!

(2부) SQL로 데이터 조회하기!

(3부) SQL로 데이터 조회하기!

(4부) SQL로 데이터 조회하기!

(5부) SQL로 데이터 조회하기!

This post is licensed under CC BY 4.0 by the author.