Mission Completed

UNION으로 복수의 테이블에서 검색 본문

selfstudy/MySQL

UNION으로 복수의 테이블에서 검색

삼지안☆ 2013. 9. 9. 15:13

UNION으로 복수의 테이블에서 검색

복수의 쿼리 결과들을 결합하여 결과 세트를 생성하기 원한다면 UNION문장을 사용할 수 있다.
다음의 예제들에 대해서, 다음과 같은 t1, t2, t3의 세 개의 테이블이 있다고 가정한다.

t1 t2 t3
ic ic di
1red -1tan 1904-01-01100
2blue 1red 2004-01-01200
3green 2004-01-01300

테이블 t1과 t2는 정수 칼럼과 문자 카럼을 가지고 있고, t3은 날짜 칼럼과 정수 칼럼을 가지고 있다.
다중 검색을 연결하는 UNION 문장을 작성하려면, 몇개의 SELECT문을 작성하고 나서 그 사이에 UNION 키워드를 넣는다(동일한 수의 칼럼을 검색해야 한다).
예를들면, 각 테이블에 있는 정수 칼럼을 선택 하려면, 다음과 같다. SELECT i FROM t1 UNION SELECT i FROM t2 UNION SELECT i FROM t3;




UNION은 다음의 특성들을 가진다.

  • 칼럼 이름과 데이터 타입
    • + UNION의 칼럼들에 대한 이름과 데이터 타입은 첫 번째 SELECT 안의 칼럼들의 이름과 타입을 따른다.
      일반적으로, UNION을 사용함으로써 해당 칼럼이 동일한 타입을 가지게 되고, MySQL은 타입 변경을 수행한다.
      따라서 UNION 내의 두번째와 그 이후의 SELECT 문장은 같은 수의 칼럼들을 선택하지만, 이름과 타입이 같을 필요는 없다.
      칼럼들은 이름이 아닌 위치에 의해 대응되는데, 이러한 이유로 이들 두 쿼리는 다른 결과를 반환하며,
      심지어 두 개의 테이블에서 동일한 값을 검색할 수도 있다.

    • + 각 문장에서, 각 칼럼의 데이터 타입은 선택된 값에 의해서 결정된다.
      첫 번째 문장(예제1)에서는 문자열과 날짜 중에서 하나가 두 번째 칼럼을 위해서 선택된다.
      결과는 문자열 칼럼이다.
      두 번째 문장(예제2)에서는 정수형과 날짜가 첫번째 칼럼에 대해서, 문자열과 정수형은 두 번째 칼럼에 대해서 선택된다.
      두 가지 모든 경우에 결과는 문자열 칼럼이 된다.
      SELECT i, c FROM t1 UNION SELECT i, d FROM t3;
      SELECT i, c FROM t1 UNION SELECT d, i FROM t3;
      
      ic
      1red
      2blue
      3green
      1001904-01-01
      2002004-01-01
      ic
      1red
      2blue
      3green
      1904-01-01100
      2004-01-01200
  • 중복 행 처리
    • + 기본적으로 UNION은 결과 세트에서 중복되는 행을 삭제한다.
      SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT * FROM t3;
      
      ic
      1red
      2blue
      3green
      -1tan
      1904-01-01100
      2004-01-01200
      t1과 t2는 둘 다 1과 'red'의 값을 포함하는 행을 가지고 있지만, 오직 하나의 행만이 출력될 수 있다.
      또한 t3는 '2004-01-01'과 200을 포함하는 두 개의 행을 가지는데, 이 중 하나는 제거되었다.

    • + UNION DISTINCT는 UNION과 동의어 이며, 두 가지 모두가 가지고 있는 행은 구별되는 값이다.
      중복된 값을 보존하려면, 첫 번째 UION 키워드에 UNION ALL을 붙이면 된다.
      SELECT * FROM t1 UNION ALL SELECT * FROM t2 UNION ALL SELECT * FROM t3;
      
      ic
      1red
      2blue
      3green
      -1tan
      1red
      1904-01-01100
      2004-01-01200
      2004-01-01200
      만약 UNION ALL을 가지고 UNION 또는 UNION DISTINCT를 혼합하면, 구별 유니온 동작은 다른 UNION ALL 보다 먼저 처리될 수 있다.
  • ORDER BY롸 LIMITS 처리
    • + UNION 결과를 정렬하러면, 쿼리 결과를 통째로 적용하는 마지막 SELECT 뒤에 ORDER BY절을 추가한다.
      하지만, UNION은 첫 번째 SELECT에 있는 칼럼 이름들을 사용하기 때문에, ORDER BY는 이 이름들을 참조해야 하고,
      마지막 SELECT에 있는 칼럼 이름들은 다른 경우라면 참조하면 안 된다.
      (SELECT i, c FROM t1) UNION (SELECT i, d FROM t3) ORDER BY c;
      
      ic
      1001904-01-01
      2002004-01-01
      2blue
      3green
      1red
    • + 만약 정렬 칼럼이 별도의 이름을 가지게 된다면, UNION의 ORDER BY는 ALIAS를 참조해야만 한다.
      또한, ORDER BY는 테이블 이르은 참조할 수 없다.
      만약 첫 번째 SELECT에서 tbl_name.col_name이 지정된 칼럼에 의해서 정렬될 필요가 있다면,
      칼럼에 별도의 이름을 지정하고 ORDER BY 절의 ALIAS를 참조하도록 한다.

      이와 비슷하게 UNION에 의해서 행의 수를 한정하기 위해서는 문장의 끝에 LIMIT을 추가한다.
      (SELECT * FROM t1) UNION (SELECT * FROM t2) UNION (SELECT * FROM t3) LIMIT 2;
      
      ic
      1red
      2blue
    • + SELECT에 적용하기 위해, ORDER BY와 LIMIT는 UNION의 개별 SELECT 내에서 사용될 수 있다.
      만약 LIMIT가 존재한다면, 개별 SELECT의 ORDER BY가 사용되고, 어떤 행에 LIMIT가 적용되었는지를 알 수 있다.
      어떤 행이 최종 UNION 결과에 나타날지에 대해서는 영향을 미치지 않는다.
      (SELECT * FROM t1 ORDER BY i LIMIT 2)
      UNION (SELECT * FROM t2 ORDER BY i LIMIT 1)
      UNION (SELECT * FROM t3 ORDER BY d LIMIT 2);
      
      ic
      1red
      2blue
      -1tan
      1904-01-01100
      2004-01-01200
    • + 만약 동일한 구조를 가지는 MyISAM 테이블의 UNION 타입의 쿼리를 실행시키기를 원한다면,
      MERGE 테이블을 셋업하고 그것에 쿼리를 실행할 수 있다.
      이는 해당 UNION 문을 사용하는 것보다 MERGE 테이블에 쿼리를 실행하는 것이 더 간단하기 때문에 유용하다.

      MERGE 테이블에 쿼리를 수행하는 것은 MERGE 테이블을 구성하는 각 개별 테이블로부터 해당 칼럼을 검색한다는 점에서
      UNION과 비슷하다. 이는 MERGE 테이블에서 SELECT는 UNION ALL(중복이 삭제되지 않는다)과 같으며,
      SELECT DISTICT는 UNION 또는 UNION DISTICT와 같다(중복은 삭제된다).

출처: Paul DuBois, 김형훈 역, 2009. 한국어판 MySQL 4th ed., chapter2 section10.