조인에 대한 SQL 개념

SQL에서와 같이 LookML의 조인은 테이블 간 관련 열을 기반으로 둘 이상의 테이블의 행을 조합하는 데 사용됩니다.

LookML에서 explore LookML 매개변수로 정의된 대로 Explore는 사용자의 데이터 쿼리 방법을 정의하기 위해 사용됩니다. Explore는 하나 이상의 또는 함께 조인된 뷰 집합으로 구성됩니다. Explore의 기본 뷰는 항상 쿼리에 포함됩니다. 조인된 뷰는 일반적으로 쿼리 충족에 필요한 경우에만 포함됩니다.

LookML 뷰는 데이터베이스의 SQL 테이블(또는 테이블 구조를 갖는 다른 요소) 또는 파생 테이블에 연결됩니다. 뷰는 데이터베이스에서 사용 가능한 필드 또는 열과 액세스 방법을 정의합니다.

다음 예시는 orders Explore의 정의입니다.

explore: orders {
  join: users {
    type: left_outer
    sql_on: ${orders.user_id} = ${users.id} ;;
    relationship: many_to_one
  }
}

Explore의 기본 뷰인 orders 뷰는 type: left_outer LookML 매개변수에 표시된 대로 SQL LEFT OUTER JOIN으로 users 뷰에 조인됩니다. sql_on LookML 매개변수로 정의되는 SQL ON 절은 table_alias.column을 사용하지 않지만 대신 to ${view_name.field_name}을 참조합니다. 따라서 테이블 이름 또는 열 이름을 데이터베이스에서 변경할 때는 한 곳에서만 이러한 변경을 수행하면 됩니다.

relationship 매개변수가 중요합니다. 조인은 행이 중복되는 팬아웃 문제를 일으킬 수 있습니다. 많은 주문이 한 명의 사용자에게만 조인된다고 지정함으로써 Looker는 이 조인이 팬아웃을 일으키지 않으므로 특별한 처리가 필요하지 않다는 것을 알 수 있습니다. 하지만 one_to_many 관계는 팬아웃을 트리거할 수 있습니다.

뷰 및 Explore의 자동 생성은 기본적으로 왼쪽 외부 조인으로 수행됩니다. 하지만 이전 예시에서는 모든 주문이 정확히 한 명의 사용자를 포함할 가능성이 매우 높기 때문에 이 예시의 조인은 내부 조인일 수 있습니다.

Explore의 생성된 SQL을 보려면 UI에서 Explore를 실행한 후 데이터 패널에서 SQL 탭을 선택합니다.

예를 들어 이전에 정의된 Orders Explore를 연 후 User IDCount 필드를 선택하면 생성된 SQL이 다음과 같이 표시됩니다.

SELECT
    `user_id` AS `orders.user_id`,
    COUNT(*) AS `orders.count`
FROM
    `thelook`.`orders` AS `orders`
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 500

이 예시에서 사용자 테이블은 전혀 참조되지 않습니다. 이 테이블은 필요한 경우에만 가져옵니다.

User ID 측정기준을 삭제하고 Users 뷰에서 ID 측정기준을 추가하면 SQL이 다음과 같이 표시됩니다.

SELECT
    `users`.`id` AS `users.id`,
    COUNT(*) AS `orders.count`
FROM
    `thelook`.`orders` AS `orders`
    INNER JOIN `thelook`.`users` AS `users` ON `orders`.`user_id` = `users`.`id`
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 500

이 경우 Users 뷰에서 선택한 항목이 있기 때문에 조인이 포함됩니다.

다음 예시에서는 이전에 정의된 orders Explore 파일의 LookML을 보여주고 order_items 뷰에 조인을 추가합니다.

explore: orders {
  join: users {
    type: inner
    sql_on: ${orders.user_id} = ${users.id} ;;
    relationship: many_to_one
  }
  join: order_items {
    type: inner
    sql_on: ${orders.id} = ${order_items.order_id} ;;
    relationship: one_to_many
  }
}

이제 UI에서 Orders Explore를 열면 Order Items 뷰가 표시됩니다. Order Items 뷰에서 OrdersCountUsersID와 함께 Total Sale Price 측정을 선택하면 Looker가 다음 SQL을 생성합니다.

SELECT
    `users`.`id` AS `users.id`,
    COUNT(DISTINCT orders.id ) AS `orders.count`,
    COALESCE(SUM(`order_items`.`sale_price`), 0) AS `order_items.total_sale_price`
FROM
    `thelook`.`orders` AS `orders`
    INNER JOIN `thelook`.`users` AS `users` ON `orders`.`user_id` = `users`.`id`
    INNER JOIN `thelook`.`order_items` AS `order_items` ON `orders`.`id` = `order_items`.`order_id`
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 500

이 예시에서 COUNT(*) AS orders.countCOUNT(DISTINCT orders.id ) AS orders.count가 되었습니다. Looker에서 발생 가능한 팬아웃 상황이 감지되었고 SQL DISTINCT 키워드가 SQL COUNT 함수에 자동으로 추가되었습니다.