본문 바로가기
연구_고민/PHP & MySql

Mysql union

by DevG 2007. 8. 7.

13.2.7.2. UNION

SELECT ...

UNION [ALL | DISTINCT] SELECT ...

[UNION [ALL | DISTINCT] SELECT ...]

UNION 은 여러 개의 SELECT문을 하나의 결과 집합으로 결합 하기 위해 사용된다.

SELECT문에서 컬럼 이름들은 리턴될 결과에 대한 컬럼 이름으로써 사용된다. SELECT문에서 선택된 컬럼 들은 같은 데이터 형을 가져야 한다. (예를 들면, 첫 번째 문장에서 선택된 첫 번째 컬럼은 다른 문들에서 선택된 첫 컬럼과 같은 데이터 형을 가져야 한다.)

만일 SELECT 컬럼 들의 데이터 형이 일치 하지 않으면, UNION에서 컬럼들의 길이화 형들이 모든 SELECT문들에서 가져온 값들로 인식 된다. 예를 들면 다음과 같은 SQL문은:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);

+---------------+

| REPEAT('a',1) |

+---------------+

| a             |

| bbbbbbbbbb    |

+---------------+

(이전 버전의 MySQL에서 첫번째 SELECT로부터 그 형과 길이가 사용되고 두번째 레코드는 길이가 1로 변경될 것이다.)

SELECT 문은 일반적인 선택 문들이나 다음 과 같은 제한을 갖는다:

  • 오직 마지막 SELECT문만이 INTO OUTFILE을 사용할 수 있다.
  • HIGH_PRIORITY UNION의 부분들은 SELECT 문과 사용될 수 없다. 첫번째 SELECT에서 명시하면 어떤 영향도 있지 않게 된다.  뒤의 SELECT문들에 사용할 경우 문법 에러가 발생한다.

UNION의 기본 행동은 중복 레코드들이 그 결과에서 제거되는 것이다. DISTINCT 옵션 keyword역시 중복 레코드를 삭제 하도록 명시 하는 것이기 때문에 아무런 영향도 갖지 않는다. ALL 옵션 keyword를 사용하면 중복 레코드 제거는 발생하지 않으며 결과는 SELECT문에서 모든 매칭되는 레코드를 포함한다.

같은 질의 안에서 UNION ALL UNION DISTINCT를 사용할 수 있다. 혼합된 UNION 타입들은 DISTINCT UNION ALL UNION을 그것의 왼쪽으로 덮어 쓰도록 취급된다. DISTINCT UNION UNION DISTINCT을 사용하여 명시적으로 만들어지거나 DISTINCT ALL keyword없이 UNION을 사용하여 암시적으로 만들어 질 수 있다.

정렬을 위해 ORDER BY LIMIT절을 사용하기 위해서, 혹은 전체 UNION 결과를 제한 하기 위해 각 SELECT문을 괄호로 묶고 마지막에 ORDER BY LIMIT을 위치 시킨다. 다음 예제는 두 가지 절 모두를 사용한다.:

(SELECT a FROM t1 WHERE a=10 AND B=1)

UNION

(SELECT a FROM t2 WHERE a=11 AND B=2)

ORDER BY a LIMIT 10;

이런 종류의 ORDER BY는 테이블 이름을 포함하는 컬럼 참조들을 사용하지 않는다. (, tbl_name.col_name 포맷으로 명명한다) 대신, SELECT 문에서 컬럼 alias를 제공하고 ORDER BY에서 그 alias를 참조 한다. (대안적으로 그 컬럼 위치를 이용하는 ORDER BY안에서 컬럼을 참조 한다. 그러나 컬럼 위치의 사용은 반대 된다.)

또한 저장 되는 컬럼이 alias라면, ORDER BY 절은 컬럼 이름이 아닌 그 alias를 참조 해야 한다. 다음 문장들 중 처음 문장은 잘 수행되지만 두번째 문장은 Unknown column 'a' in 'order clause' 에러와 함께 실패 한다:

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;

개별 SELECT ORDER BY LIMIT를 적용하기 위해서는 SELECT를 괄호로 묶어 그 안에 절을 위치 시키도록 하라:

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)

UNION

(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

개별 SELECT문을 위한 ORDER BY의 사용은 기본적으로 UNION은 레코드 집합을 순서 없이 만들게 되기 때문에 최종 결과에서 레코드들이 어떻게 나타나야 하는지 순서에 관해 아무것도 암시 하지 않는다. ORDER BY LIMIT과 함께 쓰일 경우, 그것은 SELECT를 위해 가져온 선택된 레코드의 부분 집합을 결정하기 위해 사용된다.  그러나 그것은 최종 UION 결과에서 레코드들의 순서에 영향을 주지 않는다. ORDER BY가 한 SELECT문에서 LIMIT없이 나타나는 경우 아무런 영향을 갖지 않으므로 최적화는 되지 않는다..

UNION결과에 있는 레코드들을 순서대로 각 SELECT 에 의해 취해진 레코드들의 집합으로 구성되도록 하려면, 정렬 컬럼으로 사용하기 위해 각 SELECT문에서 추가적인 컬럼을 선택하고 마지막 SELECT뒤에 ORDER BY를 추가 하도록 하라:

(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)

UNION

(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;

또한 개별 SELECT 결과들 안에서 정렬 순서를 유지 하기 위해 ORDER by 절에 두 번째 컬럼을 추가 하도록 하라:

(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)

UNION

(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;