카테고리:

쿼리 구문

WHERE

WHERE 절은 필터 역할을 하는 조건을 지정합니다. WHERE 절을 사용하여 다음을 수행할 수 있습니다.

구문

...
WHERE <predicate>
[ ... ]
Copy
predicate

부울 식입니다. 식에는 AND, OR, NOT 과 같은 논리 연산자 가 포함될 수 있습니다.

사용법 노트

  • WHERE 절의 조건자는 FROM 절 이후에 평가되는 것처럼 작동합니다(하지만 결과에 영향을 미치지 않는 경우 옵티마이저는 조건자를 재정렬할 수 있음). 예를 들어, WHERE 절의 조건자가 FROM 절의 외부 조인에 참여하는 테이블의 열을 참조하는 경우, 필터는 조인에서 반환된 행(NULL로 채워질 수 있음)에서 작동합니다.

  • NULL을 평가할 수 있는 식을 만들 때 주의하십시오.

    • 대부분의 컨텍스트에서 부울 식 NULL = NULL 은 TRUE가 아닌 NULL을 반환합니다. NULL 값을 비교하려면 IS [ NOT ] NULL 을 사용하는 것이 좋습니다.

    • WHERE 절에서 식이 NULL로 평가되면 해당 식의 행이 결과 세트에서 제거됩니다(즉, 필터링됨).

  • 목록의 최대 식 개수는 16,384개입니다. 예를 들어 제한은 다음 SELECT 문의 식 개수에 적용됩니다.

    SELECT column_x
       FROM mytable
       WHERE column_y IN (<expr1>, <expr2>, <expr3> ...);
    
    Copy

    제한에 도달하지 않도록 하려면 IN 절을 사용하여 값을 지정하는 대신 식 값이 포함된 조회 테이블과 조인을 수행하십시오. 예를 들어 이전 예의 식 값이 mylookuptable 이라는 조회 테이블에 추가되면 조회 테이블에 16,384개보다 많은 행이 있어도 다음 쿼리를 성공적으로 실행할 수 있습니다.

    SELECT column_x
      FROM mytable t
      JOIN mylookuptable l
      ON t.column_y = l.values_for_comparison;
    
    Copy

WHERE 절의 조인

WHERE 절은 주로 필터링을 위한 것이지만, WHERE 절은 여러 형식의 조인을 표현하는 데에도 사용할 수 있습니다. 조인에 대한 개념 정보는 조인 관련 작업하기 을 참조하십시오.

WHERE 절은 조인 조건을 포함함으로써 조인을 지정할 수 있습니다. 조인 조건은 JOIN 한쪽의 행이 조인의 다른 쪽 행과 일치하는지 정의하는 부울 식입니다.

다음 두 개의 동등한 쿼리는 WHERE 또는 FROM 절에서 내부 조인을 표현하는 방법을 보여줍니다.

SELECT t1.c1, t2.c2
    FROM t1, t2
    WHERE t1.c1 = t2.c2;

SELECT t1.c1, t2.c2
    FROM t1 INNER JOIN t2
        ON t1.c1 = t2.c2;
Copy

외부 조인은 WHERE 절의 (+) 구문이나 FROM 절의 OUTER JOIN 키워드를 사용하여 지정할 수 있습니다.

(+) 로 외부 조인을 지정하면 WHERE 절은 “내부”(아래 정의)인 테이블의 각 조인 열에 (+) 를 적용합니다.

참고

외부 조인의 결과에는 한 테이블의 모든 행 복사본이 포함됩니다. 이 항목에서는 행이 보존된 테이블을 “외부” 테이블이라고 하고 다른 테이블을 “내부” 테이블이라고 합니다.

  • LEFT OUTER JOIN에서 왼쪽 테이블은 외부 테이블이고 오른쪽 테이블은 내부 테이블입니다.

  • RIGHT OUTER JOIN에서 오른쪽 테이블은 외부 테이블이고 왼쪽 테이블은 내부 테이블입니다.

다음 쿼리는 FROM 절에서 조인을 지정하고 WHERE 절에서 조인을 지정하는 동등한 왼쪽 외부 조인을 보여줍니다.

SELECT t1.c1, t2.c2
FROM t1 LEFT OUTER JOIN t2
        ON t1.c1 = t2.c2;

SELECT t1.c1, t2.c2
FROM t1, t2
WHERE t1.c1 = t2.c2(+);
Copy

두 번째 쿼리에서 (+) 는 오른쪽에 있으며 내부 테이블을 식별합니다.

두 쿼리에 대한 샘플 출력은 다음과 같습니다.

+-------+-------+
| T1.C1 | T2.C2 |
|-------+-------|
|     1 |     1 |
|     2 |  NULL |
|     3 |     3 |
|     4 |  NULL |
+-------+-------+
Copy

여러 열의 테이블을 조인하는 경우 내부 테이블의 열에 (+) 표기법을 사용합니다(아래 예에서는 t2).

SELECT t1.c1, t2.c2
FROM t1, t2
WHERE t1.c1 = t2.c2 (+)
  AND t1.c3 = t2.c4 (+);
Copy

참고

(+) 주석이 나타날 수 있는 위치에는 많은 제한이 있습니다. FROM 절 외부 조인이 더 표현적입니다. Snowflake는 이미 (+) 표기법을 사용하는 코드를 이식할 때만 이 표기법을 사용할 것을 제안합니다. 새 코드는 이 표기법을 피하는 것이 좋습니다.

제한 사항은 다음과 같습니다.

  • (+) 표기법을 사용하여 FULL OUTER JOIN 을 만들 수 없습니다. LEFT OUTER JOINRIGHT OUTER JOIN 만 만들 수 있습니다. 다음은 유효하지 않습니다. 이 문은 다음 오류 메시지를 유발합니다. SQL compilation error: Outer join predicates form a cycle between 'T1' and 'T2'.

    -- NOT VALID
    select t1.c1
        from t1, t2
        where t1.c1 (+) = t2.c2 (+);
    
    Copy
  • 테이블이 쿼리에서 둘 이상의 조인에 참여하는 경우 (+) 표기법은 해당 조인 중 오직 하나 에서 테이블을 내부 테이블로 지정할 수 있습니다. 다음은 t1 이 두 조인에서 내부 테이블 역할을 하기 때문에 유효하지 않습니다. 이 문은 다음 오류 메시지를 유발합니다. SQL compilation error: Table 'T1' is outer joined to multiple tables: 'T3' and 'T2'.

    -- NOT VALID
    select t1.c1
        from t1, t2, t3
        where t1.c1 (+) = t2.c2
          and t1.c1 (+) = t3.c3;
    
    Copy

    그러나 (+) 를 사용하여 동일 SQL 문에서 다른 조인 의 내부 테이블로 다른 테이블 을 식별할 수 있습니다. 다음 예에서는 세 개의 테이블, 즉 t1, t2, t3 을 조인하며 그중 두 개는 내부 테이블(다른 조인에 있음)입니다. 이 문은 다음을 수행합니다.

    • t1t2 사이의 LEFT OUTER JOIN(여기서 t2 는 내부 테이블).

    • t2t3 사이의 LEFT OUTER JOIN(여기서 t3 은 내부 테이블).

    select t1.c1
        from t1, t2, t3
        where t1.c1 = t2.c2 (+)
          and t2.c2 = t3.c3 (+);
    
    Copy

(+) 는 테이블 및 열 이름 바로 옆에 있거나 공백으로 구분될 수 있습니다. 다음 두 가지가 모두 유효합니다.

where t1.c1 = t2.c2(+)

where t1.c1 = t2.c2 (+)
Copy

쿼리는 FROM ... ON ... 절과 WHERE 절 둘 다에 지정된 조인을 포함할 수 있습니다. 그러나 동일한 쿼리의 다른 절에 조인을 지정하면 해당 쿼리를 읽기가 더 어려워질 수 있습니다.

WHERE 절의 조인 지원은 주로, FROM ... ON ... 구문을 사용하지 않는 이전 쿼리와의 하위 호환성을 위한 것입니다. Snowflake는 조인을 사용하여 새 쿼리를 작성할 때 FROM ... ON ... 사용을 권장합니다. 자세한 내용은 JOIN 섹션을 참조하십시오.

필터링의 간단한 예

다음은 WHERE 절의 몇 가지 간단한 사용을 보여줍니다.

SELECT * FROM invoices
  WHERE invoice_date < '2018-01-01';

SELECT * FROM invoices
  WHERE invoice_date < '2018-01-01'
    AND paid = FALSE;
Copy

이 예에서는 하위 쿼리를 사용하고 평균 청구 금액보다 작은 모든 송장을 보여줍니다.

SELECT * FROM invoices
    WHERE amount < (
                   SELECT AVG(amount)
                       FROM invoices
                   )
    ;
Copy

WHERE 절에서 조인을 수행하기

WHERE 절에 조인을 지정하려면 FROM clause 절에 조인할 테이블을 나열하고 테이블을 쉼표로 구분합니다. 다음 예와 같이 WHERE 절에서 조인 조건을 필터로 지정합니다.

SELECT t1.col1, t2.col1
    FROM t1, t2
    WHERE t2.col1 = t1.col1
    ORDER BY 1, 2;
+------+------+
| COL1 | COL1 |
|------+------|
|    2 |    2 |
|    2 |    2 |
|    3 |    3 |
+------+------+
Copy

참고

쉼표 연산자는 INNER JOIN 의 이전 구문입니다. 다음 문은 새로운 구문을 사용하여 조인을 수행하는 권장 방법을 보여줍니다. 아래 쿼리는 위 쿼리와 동일합니다.

SELECT t1.col1, t2.col1
    FROM t1 JOIN t2
        ON t2.col1 = t1.col1
    ORDER BY 1, 2;
+------+------+
| COL1 | COL1 |
|------+------|
|    2 |    2 |
|    2 |    2 |
|    3 |    3 |
+------+------+
Copy

다음 섹션에서는 3개 테이블 조인을 보여주고 0, 1 또는 2 (+) 외부 조인 연산자를 사용한 동작의 차이점을 보여줍니다.

쿼리를 실행하기 전에 조인에 사용할 테이블을 만들고 로딩합니다.

create table departments (
    department_ID INTEGER,
    department_name VARCHAR,
    location VARCHAR
    );
insert into departments (department_id, department_name, location) values
    (10, 'CUSTOMER SUPPORT', 'CHICAGO'),
    (40, 'RESEARCH', 'BOSTON'),
    (80, 'Department with no employees yet', 'CHICAGO'),
    (90, 'Department with no projects or employees yet', 'EREHWON')
    ;

create table projects (
    project_id integer,
    project_name varchar,
    department_id integer
    );
insert into projects (project_id, project_name, department_id) values
    (4000, 'Detect fake product reviews', 40),
    (4001, 'Detect false insurance claims', 10),
    (9000, 'Project with no employees yet', 80),
    (9099, 'Project with no department or employees yet', NULL)
    ;

create table employees (
    employee_ID INTEGER,
    employee_name VARCHAR,
    department_id INTEGER,
    project_id INTEGER
    );
insert into employees (employee_id, employee_name, department_id, project_id)
  values
    (1012, 'May Aidez', 10, NULL),
    (1040, 'Devi Nobel', 40, 4000),
    (1041, 'Alfred Mendeleev', 40, 4001)
    ;
Copy

3방향 내부 조인을 실행합니다. 이는 (+) (또는 OUTER 키워드)를 사용하지 않으므로 내부 조인입니다. 출력에는 부서, 프로젝트, 직원이 있는 행만 포함됩니다.

SELECT d.department_name, p.project_name, e.employee_name
    FROM  departments d, projects p, employees e
    WHERE
            p.department_id = d.department_id
        AND
            e.project_id = p.project_id
    ORDER BY d.department_id, p.project_id, e.employee_id;
+------------------+-------------------------------+------------------+
| DEPARTMENT_NAME  | PROJECT_NAME                  | EMPLOYEE_NAME    |
|------------------+-------------------------------+------------------|
| CUSTOMER SUPPORT | Detect false insurance claims | Alfred Mendeleev |
| RESEARCH         | Detect fake product reviews   | Devi Nobel       |
+------------------+-------------------------------+------------------+
Copy

외부 조인을 수행합니다. 이는 두 번째 조인을 오른쪽 외부 조인으로 만들기 위해 (+) 를 사용한다는 점을 제외하고 앞의 문과 유사합니다. 그 결과, 출력에 부서가 포함된 경우, 해당 프로젝트에 직원이 없더라도 해당 부서의 모든 프로젝트가 포함됩니다.

SELECT d.department_name, p.project_name, e.employee_name
    FROM  departments d, projects p, employees e
    WHERE
            p.department_id = d.department_id
        AND
            e.project_id(+) = p.project_id
    ORDER BY d.department_id, p.project_id, e.employee_id;
+----------------------------------+-------------------------------+------------------+
| DEPARTMENT_NAME                  | PROJECT_NAME                  | EMPLOYEE_NAME    |
|----------------------------------+-------------------------------+------------------|
| CUSTOMER SUPPORT                 | Detect false insurance claims | Alfred Mendeleev |
| RESEARCH                         | Detect fake product reviews   | Devi Nobel       |
| Department with no employees yet | Project with no employees yet | NULL             |
+----------------------------------+-------------------------------+------------------+
Copy

두 개의 외부 조인을 수행합니다. 이는 두 조인을 외부 조인으로 만들기 위해 (+) 를 사용한다는 점을 제외하고 앞의 문과 동일합니다. 그 결과, 모든 부서가 포함되고(아직 프로젝트나 직원이 없는 경우에도 마찬가지) 부서와 연결된 모든 프로젝트가 포함됩니다(아직 직원이 없는 경우에도 마찬가지). 부서가 없는 프로젝트는 출력에서 제외됩니다.

SELECT d.department_name, p.project_name, e.employee_name
    FROM  departments d, projects p, employees e
    WHERE
            p.department_id(+) = d.department_id
        AND
            e.project_id(+) = p.project_id
    ORDER BY d.department_id, p.project_id, e.employee_id;
+----------------------------------------------+-------------------------------+------------------+
| DEPARTMENT_NAME                              | PROJECT_NAME                  | EMPLOYEE_NAME    |
|----------------------------------------------+-------------------------------+------------------|
| CUSTOMER SUPPORT                             | Detect false insurance claims | Alfred Mendeleev |
| RESEARCH                                     | Detect fake product reviews   | Devi Nobel       |
| Department with no employees yet             | Project with no employees yet | NULL             |
| Department with no projects or employees yet | NULL                          | NULL             |
+----------------------------------------------+-------------------------------+------------------+
Copy

(그러나 Snowflake는 WHERE 절에서 (+) 연산자를 사용하는 것보다 FROM 절에서 OUTER 키워드를 사용할 것을 권장합니다.)