SQL 명령어로 시맨틱 뷰 생성 및 관리하기
SQL 명령어로 시맨틱 뷰 생성 및 관리하기
이 주제는 DDL(SQL) 명령어를 사용해 시맨틱 뷰(semantic view)를 만들고 관리하는 방법을 설명해요. DDL 방식과 YAML 작성 방식의 비교는 시맨틱 뷰에 YAML과 DDL 중 무엇을 쓸까를 참고해요.
출처: Snowflake 문서
본문
이 주제에서 다루는 명령어는 다음과 같아요:
- CREATE SEMANTIC VIEW
- ALTER SEMANTIC VIEW
- DESCRIBE SEMANTIC VIEW
- DROP SEMANTIC VIEW
- SHOW SEMANTIC VIEWS
- SHOW SEMANTIC DIMENSIONS
- SHOW SEMANTIC DIMENSIONS FOR METRIC
- SHOW SEMANTIC FACTS
- SHOW SEMANTIC METRICS
또한 YAML 사양에서 시맨틱 뷰를 만들고 시맨틱 뷰의 사양을 가져오는 다음 저장 프로시저와 함수를 호출하는 방법도 설명해요:
- SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML
- SYSTEM$READ_YAML_FROM_SEMANTIC_VIEW
시맨틱 뷰를 만들거나 교체하는 데 필요한 권한
시맨틱 뷰를 만들거나 교체하려면 다음 권한을 가진 역할(role)을 사용해야 해요:
- 시맨틱 뷰를 만들 스키마에 대한 CREATE SEMANTIC VIEW 권한
- 시맨틱 뷰를 만들 데이터베이스와 스키마에 대한 USAGE 권한
- 시맨틱 뷰에서 사용하는 테이블과 뷰에 대한 SELECT 권한
시맨틱 뷰를 쿼리하는 데 필요한 권한에 대한 내용은 시맨틱 뷰를 쿼리하는 데 필요한 권한을 참고해요.
CREATE SEMANTIC VIEW 명령어로 시맨틱 뷰 만들기
시맨틱 뷰를 만들려면 CREATE SEMANTIC VIEW 명령어를 사용해요.
참고: YAML 사양에서 시맨틱 뷰를 만들려면
SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML저장 프로시저를 호출해요.
시맨틱 뷰는 유효해야 해요. Snowflake가 시맨틱 뷰를 검증하는 방법을 참고해요.
다음 예시는 Snowflake에서 제공하는 TPC-H 샘플 데이터를 사용해요. 이 데이터 세트에는 고객, 주문, 라인 아이템을 나타내는 단순한 비즈니스 시나리오의 테이블이 들어 있어요.
이 예시는 TPC-H 데이터 세트의 테이블을 사용해 tpch_rev_analysis라는 시맨틱 뷰를 만들어요. 이 시맨틱 뷰는 다음을 정의해요:
- 세 개의 논리적 테이블(
orders,customers,line_items) orders테이블과customers테이블 사이의 관계line_items테이블과orders테이블 사이의 관계- 메트릭 계산에 사용될 팩트(facts)
- 고객 이름, 주문 날짜, 주문이 발생한 연도에 대한 차원(dimensions)
- 주문 평균 값과 주문 내 평균 라인 아이템 수에 대한 메트릭(metrics)
CREATE SEMANTIC VIEW tpch_rev_analysis
TABLES (
orders AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.ORDERS
PRIMARY KEY (o_orderkey)
WITH SYNONYMS ('sales orders')
COMMENT = 'All orders table for the sales domain',
customers AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.CUSTOMER
PRIMARY KEY (c_custkey)
COMMENT = 'Main table for customer data',
line_items AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.LINEITEM
PRIMARY KEY (l_orderkey, l_linenumber)
COMMENT = 'Line items in orders'
)
RELATIONSHIPS (
orders_to_customers AS
orders (o_custkey) REFERENCES customers,
line_item_to_orders AS
line_items (l_orderkey) REFERENCES orders
)
FACTS (
line_items.line_item_id AS CONCAT(l_orderkey, '-', l_linenumber),
orders.count_line_items AS COUNT(line_items.line_item_id),
line_items.discounted_price AS l_extendedprice * (1 - l_discount)
COMMENT = 'Extended price after discount'
)
DIMENSIONS (
customers.customer_name AS customers.c_name
WITH SYNONYMS = ('customer name')
COMMENT = 'Name of the customer',
orders.order_date AS o_orderdate
COMMENT = 'Date when the order was placed',
orders.order_year AS YEAR(o_orderdate)
COMMENT = 'Year when the order was placed'
)
METRICS (
customers.customer_count AS COUNT(c_custkey)
COMMENT = 'Count of number of customers',
orders.order_average_value AS AVG(orders.o_totalprice)
COMMENT = 'Average order value across all orders',
orders.average_line_items_per_order AS AVG(orders.count_line_items)
COMMENT = 'Average number of line items per order'
)
COMMENT = 'Semantic view for revenue analysis';
다음 섹션에서 이 예시를 더 자세히 설명해요:
- 논리적 테이블 정의하기
- 논리적 테이블 사이의 관계 식별하기
- 날짜, 시간, 타임스탬프 또는 숫자 범위로 논리적 테이블 조인하기
- 값의 범위를 포함하는 논리적 테이블 조인하기
- 팩트, 차원, 메트릭 정의하기
- Cortex Search 서비스를 사용하는 차원 정의하기
- 파생 메트릭(derived metric) 정의하기
- 관계 경로가 여러 개일 때 메트릭에 사용할 관계 지정하기
- 메트릭에 대해 비가산(non-additive)이어야 하는 차원 식별하기
- 팩트나 메트릭을 비공개(private)로 표시하기
- Cortex Analyst에 사용자 지정 지침 제공하기
참고: 전체 예시는 SQL로 시맨틱 뷰를 만드는 예시를 참고해요.
논리적 테이블 정의하기
CREATE SEMANTIC VIEW 명령어에서 TABLES 절을 사용해 뷰 안의 논리적 테이블을 정의해요. 이 절에서 다음을 할 수 있어요:
- 물리적 테이블 이름과 선택적 별칭(alias)을 지정하거나, SQL 쿼리를 논리적 테이블로 지정하기
- 논리적 테이블에서 다음 열을 식별하기:
- 기본 키(primary key) 역할을 하는 열
- (기본 키 열 외에) 고유 값을 갖는 열
- 이런 열을 사용해 이 시맨틱 뷰에서 관계를 정의할 수 있어요.
- 테이블에 동의어(synonyms) 추가하기 (검색 가능성 향상용)
- 설명적인 주석(comment) 포함하기
앞서 제시한 예시에서 TABLES 절은 세 개의 논리적 테이블을 정의해요:
- TPC-H
orders테이블의 주문 정보를 담은orders테이블 - TPC-H
customers테이블의 고객 정보를 담은customers테이블 - TPC-H
lineitem테이블의 주문 내 라인 아이템을 담은line_items테이블
이 예시는 PRIMARY KEY 절을 사용해 각 논리적 테이블의 기본 키로 사용할 열을 식별해요. 기본 키와 고유 값은 테이블 사이의 관계 유형(예: 다대일(many-to-one) 또는 일대일(one-to-one))을 결정하는 데 도움을 줘요.
이 예시는 또한 논리적 테이블을 설명하고 데이터를 더 쉽게 검색할 수 있게 해주는 동의어와 주석도 제공해요.
TABLES (
orders AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.ORDERS
PRIMARY KEY (o_orderkey)
WITH SYNONYMS ('sales orders')
COMMENT = 'All orders table for the sales domain',
customers AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.CUSTOMER
PRIMARY KEY (c_custkey)
COMMENT = 'Main table for customer data',
line_items AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.LINEITEM
PRIMARY KEY (l_orderkey, l_linenumber)
COMMENT = 'Line items in orders'
)
논리적 테이블 사이의 관계 식별하기
CREATE SEMANTIC VIEW 명령어에서 RELATIONSHIPS 절을 사용해 뷰 안의 테이블 사이의 관계를 식별해요. 각 관계에 대해 다음을 지정해요:
-
관계의 선택적 이름
-
외래 키(foreign key)를 포함하는 논리적 테이블의 이름
-
그 테이블에서 외래 키를 정의하는 열
-
기본 키 또는 고유 값을 포함하는 논리적 테이블의 이름
-
그 테이블에서 기본 키를 정의하거나 고유 값을 포함하는 열
-
TABLES 절에서 논리적 테이블에 PRIMARY KEY를 이미 지정했다면, 관계에서 기본 키 열을 지정할 필요가 없어요.
-
TABLES 절에서 논리적 테이블에 UNIQUE 키워드가 하나만 있다면, 관계에서 해당 열을 지정할 필요가 없어요.
또한 열을 범위로 조인하려면 날짜, 시간, 타임스탬프 또는 숫자 열을 지정할 수도 있어요.
앞서 제시한 예시에서 RELATIONSHIPS 절은 두 개의 관계를 지정해요:
orders테이블과customers테이블 사이의 관계.orders테이블에서o_custkey는customers테이블의 기본 키(c_custkey)를 참조하는 외래 키예요.line_items테이블과orders테이블 사이의 관계.line_items테이블에서l_orderkey는orders테이블의 기본 키(o_orderkey)를 참조하는 외래 키예요.
RELATIONSHIPS (
orders_to_customers AS
orders (o_custkey) REFERENCES customers (c_custkey),
line_item_to_orders AS
line_items (l_orderkey) REFERENCES orders (o_orderkey)
)
날짜, 시간, 타임스탬프 또는 숫자 범위로 논리적 테이블 조인하기
기본적으로 두 논리적 테이블 사이의 관계를 지정하면 테이블은 동등(equality) 조건으로 조인돼요.
두 논리적 테이블을 날짜, 시간, 타임스탬프 또는 숫자 범위로 조인해야 한다면(한 테이블의 한 열 값이 다른 테이블의 한 열 값과 같은 범위에 있어야 하는 경우) REFERENCES 절에서 열 이름과 함께 ASOF 키워드를 지정할 수 있어요:
RELATIONSHIPS (
my_relationship AS
logical_table_1 (
col_table_1
)
REFERENCES
logical_table_2 (
ASOF col_table_2
)
)
위에서 정의한 시맨틱 뷰에 대한 쿼리는 MATCH_CONDITION 절에서 >= 비교 연산자를 사용하는 ASOF JOIN을 만들어요. 이렇게 하면 col_table_1의 값이 col_table_2의 값보다 크거나 같도록 두 테이블을 조인해요:
...
FROM logical_table_1 ASOF JOIN logical_table_2
MATCH_CONDITION (
logical_table_1.col_table_1 >= logical_table_2.col_table_2
)
...
참고: MATCH_CONDITION 절에서는 다른 비교 연산자는 지원하지 않아요.
ASOF JOIN과 함께 사용할 수 있는 것과 같은 유형의 열에 ASOF 키워드를 사용할 수 있어요.
참고: 주어진 관계의 정의에서는 ASOF 키워드를 최대 하나만 지정할 수 있어요. 이 키워드는 목록의 아무 열 앞에나 지정할 수 있어요.
예를 들어 고객, 고객 주소, 주문 데이터를 담은 테이블이 있다고 가정해 보세요:
CREATE OR REPLACE TABLE customer (
c_cust_id VARCHAR,
c_first_name VARCHAR,
c_last_name VARCHAR);
INSERT INTO customer VALUES
('cust001', 'Mary', 'Smith'),
('cust002', 'Bill', 'Wilson');
CREATE OR REPLACE TABLE customer_address (
ca_cust_id VARCHAR,
ca_zipcode VARCHAR,
ca_street_addr VARCHAR,
ca_start_date DATE,
ca_end_date DATE
);
INSERT INTO customer_address VALUES
('cust001', '94025', '100 Main Street', '2024-01-01', '2024-03-31'),
('cust001', '94026', '200 Main Street', '2024-04-01', '2024-06-30'),
('cust001', '94027', '300 Main Street', '2024-07-01', NULL),
('cust002', '94028', '400 Main Street', '2024-01-01', '2024-04-30'),
('cust002', '94029', '500 Main Street', '2024-05-01', '2024-07-31'),
('cust002', '94030', '600 Main Street', '2024-08-01', NULL);
CREATE OR REPLACE TABLE orders (
o_ord_id VARCHAR,
o_cust_id VARCHAR,
o_ord_date DATE,
o_amount NUMBER
);
INSERT INTO orders VALUES
('ord100', 'cust001', '2024-02-01', 100),
('ord101', 'cust001', '2024-02-02', 200),
('ord102', 'cust001', '2024-05-01', 300),
('ord103', 'cust001', '2024-05-02', 400),
('ord104', 'cust001', '2024-08-01', 500),
('ord105', 'cust001', '2024-08-02', 600),
('ord106', 'cust002', '2024-03-01', 100),
('ord107', 'cust002', '2024-03-02', 200),
('ord108', 'cust002', '2024-06-01', 300),
('ord109', 'cust002', '2024-06-02', 400),
('ord110', 'cust002', '2024-09-01', 500),
('ord111', 'cust002', '2024-09-02', 600);
이 예시에서 customer_address 테이블에는 고객이 지정된 주소에 거주를 시작한 시기를 나타내는 ca_start_date 열이 있어요. orders 테이블에는 주문 날짜인 o_ord_date 열이 있어요.
고객 주문 정보를 쿼리하고 주문이 발생했을 때 고객이 거주하던 곳의 우편번호를 가져오고 싶다고 가정해 보세요.
ca_start_date 열과 o_ord_date 열 사이에 ASOF 조인을 지정하는 시맨틱 뷰를 정의할 수 있어요:
CREATE OR REPLACE SEMANTIC VIEW customer_orders_view
TABLES (
customer_address UNIQUE (ca_cust_id, ca_start_date),
customer UNIQUE (c_cust_id),
orders UNIQUE (o_ord_id)
)
RELATIONSHIPS (
customer_address (ca_cust_id) REFERENCES customer,
-- Defines an ASOF JOIN on the date columns.
orders (o_cust_id, o_ord_date)
REFERENCES
customer_address (ca_cust_id, ASOF ca_start_date)
)
FACTS (
customer_address.f_zipcode AS ca_zipcode
)
DIMENSIONS (
-- Relies on the ASOF join to retrieve the zip code
-- where the order date is greater than or equal to
-- the address starting date.
orders.f_cust_zipcode AS customer_address.f_zipcode,
orders.dim_year_month AS DATE_TRUNC('month', o_ord_date)
)
METRICS (
orders.m_order_amount AS SUM(o_amount)
);
이 시맨틱 뷰를 쿼리해 각 우편번호의 월별 주문 금액 합계를 반환한다고 가정해 보세요:
SELECT * FROM SEMANTIC_VIEW (
customer_orders_view
DIMENSIONS orders.dim_year_month, orders.f_cust_zipcode
METRICS orders.m_order_amount
);
+----------------+----------------+----------------+
| DIM_YEAR_MONTH | F_CUST_ZIPCODE | M_ORDER_AMOUNT |
|----------------+----------------+----------------|
| 2024-02-01 | 94025 | 300 |
| 2024-05-01 | 94026 | 700 |
| 2024-08-01 | 94027 | 1100 |
| 2024-03-01 | 94028 | 300 |
| 2024-09-01 | 94030 | 1100 |
| 2024-06-01 | 94029 | 700 |
+----------------+----------------+----------------+
이 쿼리는 효과적으로 ASOF JOIN을 사용해 주문 날짜가 주소 시작 날짜보다 크거나 같은 조건으로 날짜 열에서 테이블을 조인해요:
...
FROM orders ASOF JOIN customer_address
MATCH_CONDITION (
orders.o_ord_date >= customer_address.ca_start_date
)
ON
orders.o_cust_id = customer_address.ca_cust_id
...
값의 범위를 포함하는 논리적 테이블 조인하기
한 테이블을 첫 번째 테이블에서 가능한 값의 범위를 정의하는 다른 테이블과 조인하려면 범위 조인(range join)을 사용할 수 있어요. 예를 들어 한 테이블이 판매 주문을 나타내고 주문이 발생한 시점의 타임스탬프 열을 가진다고 가정해 보세요. 또 다른 테이블이 회계 분기(fiscal quarters)를 나타내고 이 분기를 나타내는 별개의 시간 범위를 포함한다고 가정해 보세요. 주문 행에 주문이 발생한 회계 분기가 포함되도록 두 테이블을 조인하는 시맨틱 뷰를 만들 수 있어요.
범위를 포함하는 테이블에서 각 범위는 별개여야 해요. 두 범위는 겹칠 수 없어요.
테이블 데이터에서 범위의 가능한 최솟값이나 최댓값을 지정하려면 NULL을 사용해요.
예를 들어 다음 테이블은 서로 겹치지 않는 시간 범위 집합을 정의해요:
- 첫 번째 행은 2024년 1월 1일까지(그 날은 포함하지 않음)의 모든 것을 포함하는 범위를 다뤄요.
- 마지막 행은 2024년 3월 20일부터의 모든 것을 포함하는 범위를 다뤄요.
+---------------+------------------+-------------------------+-------------------------+
| TIME_PERIOD_ID| TIME_PERIOD_NAME | START_TIME | END_TIME |
|---------------+------------------+-------------------------+-------------------------|
| 1 | Before_January | NULL | 2024-01-01 00:00:00.000 |
| 2 | Early_January | 2024-01-01 00:00:00.000 | 2024-01-15 00:00:00.000 |
| 3 | Late_January | 2024-01-15 00:00:00.000 | 2024-02-01 00:00:00.000 |
| 4 | Early_February | 2024-02-01 00:00:00.000 | 2024-02-15 00:00:00.000 |
| 5 | Late_February | 2024-02-15 00:00:00.000 | 2024-03-01 00:00:00.000 |
| 6 | Early_March | 2024-03-01 00:00:00.000 | 2024-03-20 00:00:00.000 |
| 7 | After_March20 | 2024-03-20 00:00:00.000 | NULL |
+---------------+------------------+-------------------------+-------------------------+
참고: 두 행이 시작 열에 NULL을 포함할 수 없고, 두 행이 끝 열에 NULL을 포함할 수 없어요.
이런 경우에 범위 조인 쿼리를 지원하는 시맨틱 뷰를 설정할 수 있어요. 시맨틱 뷰를 만들 때 다음을 해야 해요:
- 시간 기간의 시작 및 종료 시간을 포함하는 논리적 테이블에 대해 두 범위가 겹칠 수 없다는 제약 조건(constraint)을 정의하기.
- CREATE SEMANTIC VIEW 명령어의 TABLES 절에서 논리적 테이블 정의에 CONSTRAINT 절을 지정해요. 구문은 CREATE SEMANTIC VIEW 주제의 CONSTRAINT 문서를 참고해요.
- 한 테이블의 타임스탬프를 포함하는 열과 다른 테이블의 시작 및 종료 시간 열 사이의 관계를 정의하기.
- CREATE SEMANTIC VIEW 명령어의 RELATIONSHIPS 절에서 BETWEEN 절을 사용해 시작 및 종료 시간을 포함하는 열을 지정해요. 구문은 CREATE SEMANTIC VIEW 주제의 RELATIONSHIP 문서를 참고해요.
예를 들어 my_time_periods 테이블이 별개의 시간 기간을 정의한다고 가정해 보세요:
CREATE OR REPLACE TABLE my_time_periods (
time_period_id INT PRIMARY KEY,
time_period_name VARCHAR(50),
start_time TIMESTAMP,
end_time TIMESTAMP
);
INSERT INTO my_time_periods (
time_period_id, time_period_name, start_time, end_time
) VALUES
(1, 'Before_January', NULL, '2024-01-01 00:00:00'::TIMESTAMP),
(2, 'Early_January', '2024-01-01 00:00:00'::TIMESTAMP, '2024-01-15 00:00:00'::TIMESTAMP),
(3, 'Late_January', '2024-01-15 00:00:00'::TIMESTAMP, '2024-02-01 00:00:00'::TIMESTAMP),
(4, 'Early_February', '2024-02-01 00:00:00'::TIMESTAMP, '2024-02-15 00:00:00'::TIMESTAMP),
(5, 'Late_February', '2024-02-15 00:00:00'::TIMESTAMP, '2024-03-01 00:00:00'::TIMESTAMP),
(6, 'Early_March', '2024-03-01 00:00:00'::TIMESTAMP, '2024-03-20 00:00:00'::TIMESTAMP),
(7, 'After_March20', '2024-03-20 00:00:00'::TIMESTAMP, NULL);
my_events 테이블이 그 시간 기간 동안 발생한 이벤트를 포착한다고 가정해 보세요:
CREATE OR REPLACE TABLE my_events (
event_id INTEGER PRIMARY KEY,
event_timestamp TIMESTAMP,
event_name VARCHAR
);
INSERT INTO my_events (event_id, event_name, event_timestamp) VALUES
(1, 'Login', '2024-01-15 10:00:00'::TIMESTAMP),
(2, 'Purchase','2024-01-15 14:30:00'::TIMESTAMP),
(3, 'Logout', '2024-01-15 18:45:00'::TIMESTAMP),
(4, 'Review', '2024-02-10 12:00:00'::TIMESTAMP),
(5, 'Support', '2024-02-20 09:30:00'::TIMESTAMP),
(6, 'Upgrade', '2024-03-05 16:00:00'::TIMESTAMP),
(7, 'Feedback','2024-03-25 11:00:00'::TIMESTAMP);
테이블을 조인하는 시맨틱 뷰를 정의할 수 있어요. my_events의 event_timestamp 열 값이 my_time_periods의 start_time과 end_time 열이 지정하는 범위 안에 있을 때 my_events의 행이 my_time_periods의 행과 조인돼요.
CREATE OR REPLACE SEMANTIC VIEW my_semantic_view_range_join
TABLES (
my_events PRIMARY KEY (event_id),
my_time_periods UNIQUE (start_time, end_time)
CONSTRAINT my_time_period_range DISTINCT RANGE BETWEEN start_time AND end_time EXCLUSIVE
)
RELATIONSHIPS (
my_time_periods_for_events AS
my_events (event_timestamp) REFERENCES
my_time_periods (BETWEEN start_time AND end_time EXCLUSIVE)
)
DIMENSIONS (
my_events.dim_event_name AS event_name,
my_events.dim_event_timestamp AS event_timestamp,
my_time_periods.dim_time_period_name AS time_period_name
)
METRICS (
my_events.m_event_count AS COUNT(*)
);
다음 쿼리는 행이 어떻게 조인되는지 보여줘요:
SELECT
sv.dim_event_name,
sv.dim_event_timestamp,
sv.dim_time_period_name,
sv.m_event_count
FROM SEMANTIC_VIEW (
my_semantic_view_range_join
METRICS my_events.m_event_count
DIMENSIONS
my_events.dim_event_name,
my_events.dim_event_timestamp,
my_time_periods.dim_time_period_name
) AS sv
ORDER BY
sv.dim_event_timestamp,
sv.dim_time_period_name;
+----------------+-------------------------+----------------------+---------------+
| DIM_EVENT_NAME | DIM_EVENT_TIMESTAMP | DIM_TIME_PERIOD_NAME | M_EVENT_COUNT |
|----------------+-------------------------+----------------------+---------------|
| Login | 2024-01-15 10:00:00.000 | Late_January | 1 |
| Purchase | 2024-01-15 14:30:00.000 | Late_January | 1 |
| Logout | 2024-01-15 18:45:00.000 | Late_January | 1 |
| Review | 2024-02-10 12:00:00.000 | Early_February | 1 |
| Support | 2024-02-20 09:30:00.000 | Late_February | 1 |
| Upgrade | 2024-03-05 16:00:00.000 | Early_March | 1 |
| Feedback | 2024-03-25 11:00:00.000 | After_March20 | 1 |
+----------------+-------------------------+----------------------+---------------+
예시에서 볼 수 있듯이 결과의 각 행에 대한 dim_time_period_name 차원은 dim_event_timestamp 차원이 속하는 시간 기간의 이름이에요.
팩트, 차원, 메트릭 정의하기
CREATE SEMANTIC VIEW 명령어에서 FACTS, DIMENSIONS, METRICS 절을 사용해 시맨틱 뷰의 팩트, 차원, 메트릭을 정의해요.
시맨틱 뷰에는 차원 또는 메트릭을 최소한 하나는 정의해야 해요.
각 팩트, 차원, 메트릭에 대해 다음을 지정해요:
- 그것이 속한 논리적 테이블
-
참고: 파생 메트릭(한 논리적 테이블에 특정되지 않는 메트릭)을 정의하려면 논리적 테이블 이름을 생략해야 해요. 파생 메트릭 정의하기를 참고해요.
-
- 팩트, 차원, 메트릭의 이름
- 그것을 계산할 SQL 표현식
-
참고: 차원에 대해 차원에 사용할 Cortex Search 서비스를 지정할 수 있어요. 자세한 내용은 Cortex Search 서비스를 사용하는 차원 정의하기를 참고해요.
-
- 선택적 동의어와 주석
-
참고: 메트릭이 특정 차원에 걸쳐 집계되어서는 안 된다면 그 차원을 비가산(non-additive)으로 지정해야 해요. 자세한 내용은 메트릭에 대해 비가산이어야 하는 차원 식별하기를 참고해요.
-
앞서 제시한 예시는 여러 팩트, 차원, 메트릭을 정의해요:
FACTS (
line_items.line_item_id AS CONCAT(l_orderkey, '-', l_linenumber),
orders.count_line_items AS COUNT(line_items.line_item_id),
line_items.discounted_price AS l_extendedprice * (1 - l_discount)
COMMENT = 'Extended price after discount'
)
DIMENSIONS (
customers.customer_name AS customers.c_name
WITH SYNONYMS = ('customer name')
COMMENT = 'Name of the customer',
orders.order_date AS o_orderdate
COMMENT = 'Date when the order was placed',
orders.order_year AS YEAR(o_orderdate)
COMMENT = 'Year when the order was placed'
)
METRICS (
customers.customer_count AS COUNT(c_custkey)
COMMENT = 'Count of number of customers',
orders.order_average_value AS AVG(orders.o_totalprice)
COMMENT = 'Average order value across all orders',
orders.average_line_items_per_order AS AVG(orders.count_line_items)
COMMENT = 'Average number of line items per order'
)
참고: 윈도우 함수를 사용하는 메트릭을 정의하기 위한 추가 지침은 윈도우 함수 메트릭 정의 및 쿼리를 참고해요.
샘플 값과 enum 표시자 추가하기
SAMPLE_VALUES 절을 사용해 차원과 팩트에 대한 대표적인 샘플 값을 제공할 수 있어요. 샘플 값은 Cortex Analyst가 열의 데이터 범위를 이해해 더 정확한 SQL 쿼리를 생성하는 데 도움을 줘요.
차원의 경우 샘플 값이 가능한 값의 완전한 집합을 나타낸다는 것을 표시하기 위해 IS_ENUM을 추가할 수도 있어요. IS_ENUM이 설정되면 Cortex Analyst는 열을 필터링할 때 그 값들 중에서만 선택해요. IS_ENUM은 차원에서만 유효해요(팩트에서는 안 됨). SAMPLE_VALUES와 IS_ENUM을 모두 지정하면 SAMPLE_VALUES가 먼저 나와야 해요. SAMPLE_VALUES 없이 IS_ENUM만 사용할 수도 있어요.
DIMENSIONS (
t1.region AS region
COMMENT = 'Sales region'
SAMPLE_VALUES ('East', 'West', 'North', 'South')
IS_ENUM,
t1.warehouse_name AS WAREHOUSE_NAME
COMMENT = 'Name of the warehouse'
SAMPLE_VALUES ('SMALL', 'CLOUD_SERVICES_ONLY', 'SP_WAREHOUSE')
)
FACTS (
t1.amount AS amount
COMMENT = 'Transaction amount'
SAMPLE_VALUES ('100', '250', '500', '1000')
)
이 예시에서 region은 네 값이 가능한 유일한 지역이므로 IS_ENUM을 사용해요. warehouse_name은 나열된 예시 외에 추가 웨어하우스가 존재할 수 있으므로 IS_ENUM 없이 SAMPLE_VALUES를 사용해요.
이 매개변수에 대한 자세한 내용은 SAMPLE_VALUES 및 IS_ENUM 매개변수 설명을 참고해요.
Cortex Search 서비스를 사용하는 차원 정의하기
Cortex Search 서비스를 사용하는 차원을 정의하려면 WITH CORTEX SEARCH SERVICE 절을 Cortex Search 서비스의 이름으로 설정해요. 서비스가 다른 데이터베이스나 스키마에 있다면 서비스 이름을 한정(qualify)해요. 예를 들어:
DIMENSIONS (
my_table.my_dimension AS my_dimension_expression
WITH CORTEX SEARCH SERVICE my_db.my_schema.my_dimension_search_service
)
파생 메트릭 정의하기
메트릭을 정의할 때 메트릭이 속한 논리적 테이블의 이름을 지정해요. 이것은 메트릭이 집계되는 논리적 테이블이에요.
서로 다른 논리적 테이블의 메트릭에 기반한 메트릭을 정의하고 싶다면 파생 메트릭(derived metric)을 정의할 수 있어요. 파생 메트릭은 특정 논리적 테이블이 아니라 시맨틱 뷰에 범위가 지정된 메트릭이에요. 파생 메트릭은 여러 논리적 테이블의 메트릭을 결합할 수 있어요.
파생 메트릭의 정의에서는 논리적 테이블 이름을 생략해요.
예를 들어 메트릭 table_1.metric_1과 table_2.metric_2의 합인 my_derived_metric_1 메트릭을 정의하려 한다고 가정해 보세요. my_derived_metric_1을 정의할 때 이름을 논리적 테이블 이름으로 한정하지 않아요:
CREATE SEMANTIC VIEW sv_with_derived_metrics
TABLES (
table_1 PRIMARY KEY (column_1),
table_2 PRIMARY KEY (column_2)
)
...
METRICS (
table_1.metric_1 AS SUM(...),
table_2.metric_2 AS SUM(...),
my_derived_metric_1 AS table_1.metric_1 + table_2.metric_2
)
...
표현식에서 다른 파생 메트릭을 사용할 수도 있어요. 예를 들어:
METRICS (
...
my_derived_metric_1 AS table_1.metric_1 + table_2.metric_2,
my_view_metric_2 AS my_derived_metric_1 + table_3.metric_3
)
파생 메트릭을 정의할 때 다음 제한 사항을 주의하세요:
- 파생 메트릭과 일반 메트릭에 같은 이름을 사용할 수 없어요.
- 파생 메트릭의 표현식은 다음을 사용할 수 있어요:
- 시맨틱 뷰의 아무 논리적 테이블에서 정의된 차원과 팩트의 집계
- 시맨틱 뷰의 아무 논리적 테이블에서 정의된 메트릭의 스칼라 표현식
- 다른 파생 메트릭
다음 예시에서:
derived_metric_1은 두 메트릭과 함께 스칼라 표현식을 사용해요.derived_metric_2는 차원의 집계를 사용해요.derived_metric_3은 다른 파생 메트릭에 차원 집계를 더해요.
CREATE OR REPLACE SEMANTIC VIEW sv_derived_metrics
TABLES (t1)
DIMENSIONS (t1.dim1 AS t1.col1)
METRICS (
t1.m1 AS SUM(t1.col1),
t2.m2 AS SUM(t1.col2),
derived_metric_1 AS t1.m1 + t2.m2,
derived_metric_2 AS SUM(t1.dim1),
derived_metric_3 AS SUM(t1.dim1) + derived_metric_2
)
...
- 표현식에서 이름이 모호하지 않다면 메트릭, 차원, 팩트의 이름을 한정할 필요가 없어요. 예를 들어:
METRICS (
table_1.metric_1 AS ...,
table_1.my_unique_metric_name AS ...,
table_2.metric_1 AS ...,
my_derived_metric_1 AS table_1.metric_1 + my_unique_metric_name
)
metric_1이라는 이름의 메트릭이 두 개이므로 metric_1은 table_1로 한정해야 하지만, my_unique_metric_name은 이름이 고유하므로 한정할 필요가 없어요.
- 파생 메트릭 표현식에서는 다음을 사용할 수 없어요:
- 메트릭의 집계
- 윈도우 함수
- 물리적 열에 대한 참조
- 집계되지 않은 팩트나 차원에 대한 참조
- 일반 메트릭, 차원, 팩트의 표현식에서는 파생 메트릭을 사용할 수 없어요. 오직 다른 파생 메트릭만 그 표현식에서 파생 메트릭을 사용할 수 있어요.
관계 경로가 여러 개일 때 메트릭에 사용할 관계 지정하기
어떤 경우에는 시맨틱 뷰의 두 특정 논리적 테이블 사이에 관계 경로가 여러 개 존재할 수 있어요. 이 경우 메트릭을 정의할 때 사용할 관계 경로를 지정해야 해요.
여러 관계 경로의 문제점
항공편과 공항에 대한 정보를 담은 두 테이블이 있다고 가정해 보세요:
CREATE OR REPLACE TABLE airports (
airport_code VARCHAR PRIMARY KEY,
city_name VARCHAR,
airport_region_code VARCHAR
);
INSERT INTO airports VALUES
('SEA', 'Seattle', 'NA'),
('SFO', 'San Francisco', 'NA'),
('PVG', 'Shanghai', 'AS');
SELECT * FROM airports;
+--------------+--------------+---------------------+
| AIRPORT_CODE | CITY_NAME | AIRPORT_REGION_CODE |
|--------------+--------------+---------------------|
| SEA | Seattle | NA |
| SFO | San Francisco| NA |
| PVG | Shanghai | AS |
+--------------+--------------+---------------------+
CREATE OR REPLACE TABLE flights (
flight_id INTEGER PRIMARY KEY,
departure_airport VARCHAR,
arrival_airport VARCHAR,
is_late BOOLEAN,
aircraft_id INTEGER,
departure_time DATETIME,
arrival_time DATETIME
);
INSERT INTO flights VALUES
(1, 'SFO', 'SEA', true, 1, '2025-01-03 06:00:00', '2025-01-03 11:00:00'),
(2, 'SEA', 'SFO', false, 2, '2025-01-03 11:00:00', '2025-01-03 16:00:00'),
(3, 'SEA', 'PVG', false, 3, '2025-01-03 11:00:00', '2025-01-04 11:00:00'),
(4, 'SFO', 'PVG', true, 1, '2025-01-03 06:00:00', '2025-01-04 11:00:00');
SELECT * FROM flights;
+-----------+-------------------+-----------------+---------+-------------+-------------------------+-------------------------+
| FLIGHT_ID | DEPARTURE_AIRPORT | ARRIVAL_AIRPORT | IS_LATE | AIRCRAFT_ID | DEPARTURE_TIME | ARRIVAL_TIME |
|-----------+-------------------+-----------------+---------+-------------+-------------------------+-------------------------|
| 1 | SFO | SEA | True | 1 | 2025-01-03 06:00:00.000 | 2025-01-03 11:00:00.000 |
| 2 | SEA | SFO | False | 2 | 2025-01-03 11:00:00.000 | 2025-01-03 16:00:00.000 |
| 3 | SEA | PVG | False | 3 | 2025-01-03 11:00:00.000 | 2025-01-04 11:00:00.000 |
| 4 | SFO | PVG | True | 1 | 2025-01-03 06:00:00.000 | 2025-01-04 11:00:00.000 |
+-----------+-------------------+-----------------+---------+-------------+-------------------------+-------------------------+
특정 도시에서 출발하고 도착하는 총 항공편 수에 대한 정보를 제공하는 시맨틱 뷰를 정의한다고 가정해 보세요:
CREATE OR REPLACE SEMANTIC VIEW flights_sv
TABLES (
flights PRIMARY KEY (flight_id),
airports PRIMARY KEY (airport_code)
) RELATIONSHIPS (
flight_departure_airport AS flights (departure_airport) REFERENCES airports (airport_code),
flight_arrival_airport AS flights (arrival_airport) REFERENCES airports (airport_code)
) DIMENSIONS (
airports.city_name AS city_name
) METRICS (
flights.m_flight_count AS COUNT(flight_id)
);
이 시맨틱 뷰는 flights 테이블과 airports 테이블 사이의 서로 다른 두 관계(flight_departure_airport와 flight_arrival_airport)를 지정해요. 테이블 사이에 관계 경로가 여러 개 있으므로 m_flight_count 메트릭을 쿼리하고 airports.city_name 차원(또는 airports 테이블의 아무 차원)을 선택하면 실패해요:
SELECT * FROM SEMANTIC_VIEW (
flights_sv
METRICS flights.m_flight_count
DIMENSIONS airports.city_name
);
010246 (42601): SQL compilation error:
Invalid dimension specified: Multi-path relationship between the dimension entity 'AIRPORTS'
and the base metric or dimension entity 'FLIGHTS' is not supported.
flights 테이블과 airports 테이블 사이에 경로가 여러 개 있으므로 쿼리가 실패해요. 만약 쿼리가 airports 테이블에서 차원을 선택하지 않았다면 쿼리는 성공했을 거예요.
사용할 관계 지정하기
CREATE SEMANTIC VIEW 명령어의 메트릭 정의에서 USING 절에 사용할 관계를 지정할 수 있어요:
METRICS (
<table_alias>.<metric>
[USING ( <relationship_name> [, ...])]
AS <sql_expr>
[, ...]
)
참고:
지정하는 각 관계는 메트릭을 포함하는 논리적 테이블에서 시작해야 해요. 예를 들어 다음을 지정하려 한다고 가정해 보세요:
METRICS ( table_a.metric_a USING (table_a_to_table_b) ...
table_a_to_table_b관계는table_a에서 시작해야 해요:RELATIONSHIPS ( table_a_to_table_b AS table_a (col_1) REFERENCES table_b (col_1) ...관계의 시퀀스(예:
table_a_to_table_b와table_b_to_table_c)는 지정할 수 없어요. 각 관계는 메트릭을 포함하는 논리적 테이블에서 시작해야 해요.메트릭이 포함된 논리적 테이블에서 서로 다른 테이블로의 관계를 식별해야 한다면 USING 절에서 관계를 지정할 수 있어요. 예를 들어
table_a에서table_b로, 그리고table_a에서table_c로의 특정 관계로 메트릭이 계산되기를 원한다고 가정해 보세요. 이 경우 USING 절에서 두 관계를 모두 지정해요:METRICS ( table_a.metric_a USING (table_a_to_table_b, table_a_to_table_c) ...파생 메트릭에서는 USING 절을 지정할 수 없어요.
예를 들어 다음 문은 특정 관계를 사용하는 두 개의 추가 메트릭을 정의해요:
flight_departure_airport관계를 사용하는m_flight_departure_countflight_arrival_airport관계를 사용하는m_flight_arrival_count
CREATE OR REPLACE SEMANTIC VIEW flights_sv
TABLES (
flights PRIMARY KEY (flight_id),
airports PRIMARY KEY (airport_code)
) RELATIONSHIPS (
flight_departure_airport AS flights (departure_airport) REFERENCES airports (airport_code),
flight_arrival_airport AS flights (arrival_airport) REFERENCES airports (airport_code)
) DIMENSIONS (
airports.city_name AS city_name
) METRICS (
flights.m_flight_count AS COUNT(flight_id),
flights.m_flight_departure_count USING (flight_departure_airport) AS flights.m_flight_count,
flights.m_flight_arrival_count USING (flight_arrival_airport) AS flights.m_flight_count
);
이 뷰를 쿼리할 때 특정 관계를 사용하는 두 개의 새 메트릭을 지정할 수 있어요:
SELECT * FROM SEMANTIC_VIEW (
flights_sv
METRICS flights.m_flight_arrival_count, flights.m_flight_departure_count
DIMENSIONS airports.city_name
);
+------------------------+--------------------------+--------------+
| M_FLIGHT_ARRIVAL_COUNT | M_FLIGHT_DEPARTURE_COUNT | CITY_NAME |
|------------------------+--------------------------+--------------|
| 1 | 2 | San Francisco|
| 1 | 2 | Seattle |
| 2 | NULL | Shanghai |
+------------------------+--------------------------+--------------+
같은 관계에 의존하는 차원 추가하기
앞선 예시의 쿼리는 관계가 기반이 되는 airports 논리적 테이블에 있는 airports.city_name 차원을 사용했어요.
서로 다른 논리적 테이블의 차원을 뷰에 추가하면, 그 차원에 대한 쿼리는 앞서 지정한 관계의 혜택을 받아요.
예를 들어 airports 테이블의 airport_region_code 열에 지정된 공항 지역에 대한 추가 정보를 담은 regions라는 테이블을 만들었다고 가정해 보세요:
CREATE OR REPLACE TABLE regions (
region_code VARCHAR PRIMARY KEY,
region_name VARCHAR
);
INSERT INTO regions VALUES
('NA', 'North America'),
('AS', 'Asia');
SELECT * FROM regions;
+-------------+---------------+
| REGION_CODE | REGION_NAME |
|-------------+---------------|
| NA | North America |
| AS | Asia |
+-------------+---------------+
앞서 정의한 시맨틱 뷰를 확장해 지역 이름을 반환할 수 있어요:
regions테이블에 대한 새 논리적 테이블 추가하기regions테이블과airports테이블 사이의 관계 추가하기- 지역 이름에 대한 차원 추가하기
regions 테이블과 airports 테이블 사이에는 관계가 하나뿐이므로 메트릭의 USING 절을 추가로 변경할 필요가 없어요.
CREATE OR REPLACE SEMANTIC VIEW flights_by_regions_sv
TABLES (
flights PRIMARY KEY (flight_id),
airports PRIMARY KEY (airport_code),
regions PRIMARY KEY (region_code)
) RELATIONSHIPS (
flight_departure_airport AS flights (departure_airport) REFERENCES airports (airport_code),
flight_arrival_airport AS flights (arrival_airport) REFERENCES airports (airport_code),
airport_region AS airports (airport_region_code) REFERENCES regions (region_code)
) DIMENSIONS (
airports.city_name AS city_name,
regions.region_name AS region_name
) METRICS (
flights.m_flight_count AS COUNT(flight_id),
flights.m_flight_departure_count USING (flight_departure_airport) AS flights.m_flight_count,
flights.m_flight_arrival_count USING (flight_arrival_airport) AS flights.m_flight_count
);
뷰를 쿼리해 region_name 차원을 지정하고 사용할 관계에 모호성이 있다면 USING 절이 사용할 관계를 결정해요:
SELECT * FROM SEMANTIC_VIEW (
flights_by_regions_sv
METRICS flights.m_flight_arrival_count, flights.m_flight_departure_count
DIMENSIONS regions.region_name
);
+------------------------+--------------------------+---------------+
| M_FLIGHT_ARRIVAL_COUNT | M_FLIGHT_DEPARTURE_COUNT | REGION_NAME |
|------------------------+--------------------------+---------------|
| 2 | 4 | North America |
| 2 | NULL | Asia |
+------------------------+--------------------------+---------------+
다른 테이블에 대한 관계 지정하기
시맨틱 뷰가 여러 테이블의 차원을 사용하고, 이 차원들에 사용할 관계를 지정해야 한다면 USING 절에 여러 관계를 지정할 수 있어요.
예를 들어 airports 테이블의 공항에 대한 날씨 정보를 담은 weather라는 테이블을 만들었다고 가정해 보세요:
CREATE OR REPLACE TABLE weather (
airport_code VARCHAR PRIMARY KEY,
weather_condition VARCHAR,
start_date DATETIME,
end_date DATETIME
);
INSERT INTO weather VALUES
('SEA', 'rainy', '2025-01-01 10:00:00', '2025-01-01 12:00:00'),
('SEA', 'rainy', '2025-01-03 10:00:00', '2025-01-03 12:00:00'),
('SFO', 'sunny', '2025-01-03 05:00:00', '2025-01-03 09:00:00'),
('SFO', 'sunny', '2025-01-03 10:00:00', '2025-01-03 18:00:00'),
('PVG', 'cloudy', '2025-01-04 10:00:00', '2025-01-04 12:00:00');
SELECT * FROM weather;
+--------------+-------------------+-------------------------+-------------------------+
| AIRPORT_CODE | WEATHER_CONDITION | START_DATE | END_DATE |
|--------------+-------------------+-------------------------+-------------------------|
| SEA | rainy | 2025-01-01 10:00:00.000 | 2025-01-01 12:00:00.000 |
| SEA | rainy | 2025-01-03 10:00:00.000 | 2025-01-03 12:00:00.000 |
| SFO | sunny | 2025-01-03 05:00:00.000 | 2025-01-03 09:00:00.000 |
| SFO | sunny | 2025-01-03 10:00:00.000 | 2025-01-03 18:00:00.000 |
| PVG | cloudy | 2025-01-04 10:00:00.000 | 2025-01-04 12:00:00.000 |
+--------------+-------------------+-------------------------+-------------------------+
앞서 정의한 시맨틱 뷰를 확장해 날씨 상태를 반환할 수 있어요:
weather테이블에 대한 새 논리적 테이블 추가하기weather테이블과flights테이블 사이에 두 개의 관계 추가하기 (출발 항공편용 하나, 도착 항공편용 하나)- 날씨 정보에 대한 차원 추가하기
- 메트릭이
weather테이블과flights테이블 사이의 두 개의 새 관계도 사용하도록 지정하기
CREATE OR REPLACE SEMANTIC VIEW flights_and_weather_sv
TABLES (
flights PRIMARY KEY (flight_id),
airports PRIMARY KEY (airport_code),
weather PRIMARY KEY (airport_code, start_date, end_date)
) RELATIONSHIPS (
flight_departure_airport AS flights (departure_airport) REFERENCES airports (airport_code),
flight_arrival_airport AS flights (arrival_airport) REFERENCES airports (airport_code),
flight_departure_weather AS flights (departure_airport, departure_time) REFERENCES weather (airport_code, BETWEEN start_date AND end_date EXCLUSIVE),
flight_arrival_weather AS flights (arrival_airport, arrival_time) REFERENCES weather (airport_code, BETWEEN start_date AND end_date EXCLUSIVE)
) DIMENSIONS (
airports.city_name AS city_name,
weather.weather_condition AS weather_condition
) METRICS (
flights.m_flight_count AS COUNT(flight_id),
flights.m_flight_departure_count USING (flight_departure_airport, flight_departure_weather) AS flights.m_flight_count,
flights.m_flight_arrival_count USING (flight_arrival_airport, flight_arrival_weather) AS flights.m_flight_count
);
뷰를 쿼리해 weather_condition 차원을 지정하면 USING 절이 사용되는 관계를 결정해요:
SELECT * FROM SEMANTIC_VIEW (
flights_by_regions_sv
METRICS flights.m_flight_arrival_count, flights.m_flight_departure_count
DIMENSIONS weather.weather_condition
);
+------------------------+--------------------------+-------------------+
| M_FLIGHT_ARRIVAL_COUNT | M_FLIGHT_DEPARTURE_COUNT | WEATHER_CONDITION |
|------------------------+--------------------------+-------------------|
| 2 | NULL | cloudy |
| 1 | 2 | sunny |
| 1 | 2 | rainy |
+------------------------+--------------------------+-------------------+
특정 관계를 사용하는 메트릭에 기반한 파생 메트릭 정의하기
파생 메트릭에서는 USING 절을 지정할 수 없지만, USING 절을 지정하는 메트릭을 사용하는 파생 메트릭을 정의할 수는 있어요.
예를 들어 다음 시맨틱 뷰는 두 개의 파생 메트릭을 정의해요:
global_m_departure_arrival_ratioglobal_m_departure_arrival_sum
이 파생 메트릭들의 정의는 둘 다 USING 절을 지정하는 flights.m_flight_departure_count와 flights.m_flight_arrival_count 메트릭을 사용해요:
CREATE OR REPLACE SEMANTIC VIEW flights_derived_metrics_sv
TABLES (
flights PRIMARY KEY (flight_id),
airports PRIMARY KEY (airport_code)
) RELATIONSHIPS (
flight_departure_airport AS flights (departure_airport) REFERENCES airports (airport_code),
flight_arrival_airport AS flights (arrival_airport) REFERENCES airports (airport_code)
) DIMENSIONS (
airports.city_name AS city_name
) METRICS (
flights.m_flight_count AS COUNT(flight_id),
flights.m_flight_departure_count USING (flight_departure_airport) AS flights.m_flight_count,
flights.m_flight_arrival_count USING (flight_arrival_airport) AS flights.m_flight_count,
global_m_departure_arrival_ratio AS DIV0(flights.m_flight_departure_count, flights.m_flight_arrival_count),
global_m_departure_arrival_sum AS flights.m_flight_departure_count + flights.m_flight_arrival_count
);
SELECT * FROM SEMANTIC_VIEW (
flights_derived_metrics_sv
METRICS global_m_departure_arrival_ratio,
flights.m_flight_arrival_count, flights.m_flight_departure_count
DIMENSIONS airports.city_name
);
+------------------------+--------------------------+----------------------------------+--------------+
| M_FLIGHT_ARRIVAL_COUNT | M_FLIGHT_DEPARTURE_COUNT | GLOBAL_M_DEPARTURE_ARRIVAL_RATIO | CITY_NAME |
|------------------------+--------------------------+----------------------------------+--------------|
| 1 | 2 | 2.000000 | Seattle |
| 1 | 2 | 2.000000 | San Francisco|
| 2 | NULL | NULL | Shanghai |
+------------------------+--------------------------+----------------------------------+--------------+
메트릭에 대해 비가산이어야 하는 차원 식별하기
어떤 경우에는 메트릭이 특정 차원에 걸쳐 집계되어서는 안 돼요. 이런 경우 차원을 비가산(non-additive)으로 표시할 수 있어요.
일부 차원에 걸쳐 메트릭을 집계할 때의 문제 이해하기
특정 날짜에 각 고객의 당좌(checking) 및 저축(savings) 계좌 잔액을 담은 테이블이 있다고 가정해 보세요.
CREATE OR REPLACE TABLE bank_accounts (
customer_id VARCHAR,
account_type VARCHAR,
year NUMBER,
month NUMBER,
day NUMBER,
balance NUMBER
);
INSERT INTO bank_accounts VALUES
('cust-001', 'checking', 2024, 01, 01, 100),
('cust-001', 'savings', 2024, 01, 01, 110),
('cust-001', 'checking', 2024, 02, 10, 140),
('cust-001', 'savings', 2024, 02, 10, 150),
('cust-001', 'checking', 2024, 03, 15, 200),
('cust-001', 'savings', 2024, 03, 30, 210),
('cust-001', 'checking', 2025, 02, 15, 280),
('cust-001', 'savings', 2025, 02, 15, 290),
('cust-001', 'checking', 2025, 03, 20, 300),
('cust-001', 'savings', 2025, 03, 20, 310),
('cust-002', 'checking', 2025, 03, 30, 200),
('cust-002', 'savings', 2025, 03, 30, 310);
SELECT * FROM bank_accounts;
+-------------+--------------+------+-------+-----+---------+
| CUSTOMER_ID | ACCOUNT_TYPE | YEAR | MONTH | DAY | BALANCE |
|-------------+--------------+------+-------+-----+---------|
| cust-001 | checking | 2024 | 1 | 1 | 100 |
| cust-001 | savings | 2024 | 1 | 1 | 110 |
| cust-001 | checking | 2024 | 2 | 10 | 140 |
| cust-001 | savings | 2024 | 2 | 10 | 150 |
| cust-001 | checking | 2024 | 3 | 15 | 200 |
| cust-001 | savings | 2024 | 3 | 30 | 210 |
| cust-001 | checking | 2025 | 2 | 15 | 280 |
| cust-001 | savings | 2025 | 2 | 15 | 290 |
| cust-001 | checking | 2025 | 3 | 20 | 300 |
| cust-001 | savings | 2025 | 3 | 20 | 310 |
| cust-002 | checking | 2025 | 3 | 30 | 200 |
| cust-002 | savings | 2025 | 3 | 30 | 310 |
+-------------+--------------+------+-------+-----+---------+
다음을 포함하는 시맨틱 뷰를 정의하려 한다고 가정해 보세요:
- 다음 차원들:
- 고객 ID
- 계좌 유형
- 연도
- 월
- 일
- 잔액 합계에 대한 메트릭
다음 문장은 위에 나열한 차원과 메트릭을 포함하는 시맨틱 뷰를 만들어요:
CREATE OR REPLACE SEMANTIC VIEW bank_accounts_sv
TABLES (
bank_accounts
)
DIMENSIONS (
bank_accounts.customer_id_dim AS bank_accounts.customer_id,
bank_accounts.account_type_dim AS bank_accounts.account_type,
bank_accounts.year_dim AS bank_accounts.year,
bank_accounts.month_dim AS bank_accounts.month,
bank_accounts.day_dim AS bank_accounts.day
)
METRICS (
bank_accounts.m_account_balance AS SUM(balance)
);
각 고객의 연말 당좌 및 저축 계좌의 총 잔액을 가져오려면 m_account_balance 메트릭을 쿼리하고 customer_id_dim과 year_dim 차원을 지정할 수 있어요.
그러나 m_account_balance 메트릭은 날짜 차원에 의해 집계되므로 각 고객의 각 날짜 잔액의 합이 돼요.
SELECT * FROM SEMANTIC_VIEW (
bank_accounts_sv
METRICS bank_accounts.m_account_balance
DIMENSIONS customer_id_dim, year_dim
)
ORDER BY customer_id_dim, year_dim;
+-------------------+-----------------+----------+
| M_ACCOUNT_BALANCE | CUSTOMER_ID_DIM | YEAR_DIM |
|-------------------+-----------------+----------|
| 910 | cust-001 | 2024 |
| 1180 | cust-001 | 2025 |
| 510 | cust-002 | 2025 |
+-------------------+-----------------+----------+
위 예시에서 2024년 cust-001의 경우 910은 각 날짜의 잔액 합(100 + 110 + 140 + 150 + 200 + 210)이에요.
특정 차원에 걸쳐 메트릭이 집계되지 않도록 방지하기
메트릭이 날짜 차원에 의해 집계되지 않도록 하려면 시맨틱 뷰를 만들 때 NON ADDITIVE BY 절에 날짜 차원을 지정해요:
CREATE OR REPLACE SEMANTIC VIEW bank_accounts_sv
TABLES (
bank_accounts
)
DIMENSIONS (
bank_accounts.customer_id_dim AS bank_accounts.customer_id,
bank_accounts.account_type_dim AS bank_accounts.account_type,
bank_accounts.year_dim AS bank_accounts.year,
bank_accounts.month_dim AS bank_accounts.month,
bank_accounts.day_dim AS bank_accounts.day
)
METRICS (
bank_accounts.m_account_balance
NON ADDITIVE BY (year_dim, month_dim, day_dim)
AS SUM(balance)
);
참고:
- 메트릭에서 NON ADDITIVE BY 절을 지정하면, 파생되지 않은 메트릭의 정의에서 해당 메트릭을 참조할 수 없어요. 비가산 차원을 지정하는 메트릭은 파생 메트릭만 참조할 수 있어요.
- NON ADDITIVE BY 절을 지정하면 메트릭이 반가산(semi-additive) 메트릭이 돼요.
이 시맨틱 뷰를 쿼리하면 m_account_balance 메트릭은 더 이상 날짜 차원에 의해 집계되지 않아요. 쿼리는 쿼리된 차원의 각 그룹에서 기간이 끝날 때의 계좌 잔액을 집계해요.
SELECT * FROM SEMANTIC_VIEW (
bank_accounts_sv
METRICS bank_accounts.m_account_balance
DIMENSIONS customer_id_dim, year_dim
)
ORDER BY customer_id_dim, year_dim;
+-------------------+-----------------+----------+
| M_ACCOUNT_BALANCE | CUSTOMER_ID_DIM | YEAR_DIM |
|-------------------+-----------------+----------|
| 210 | cust-001 | 2024 |
| 610 | cust-001 | 2025 |
| 510 | cust-002 | 2025 |
+-------------------+-----------------+----------+
위 예시에서 2024년 cust-001의 경우 210은 데이터가 있는 연도의 마지막 날의 당좌 및 저축 계좌 잔액의 합이에요:
- 2024년에 데이터가 있는 마지막 날은
2024-03-30이에요. - 당좌 계좌에는 그 날짜의 행이 없으므로 결과 메트릭은 저축 계좌의 잔액(
210)이에요.
또 다른 예시로, 모든 고객의 연말 총 계좌 잔액만 원한다면 year_dim 차원을 지정할 수 있어요.
날짜 차원이 비가산으로 표시되어 있으므로 쿼리는 각 고객의 당좌 및 저축 계좌 잔액에 대해 기간(날짜 기준)이 끝날 때의 값을 합산해요.
SELECT * FROM SEMANTIC_VIEW (
bank_accounts_sv
METRICS bank_accounts.m_account_balance
DIMENSIONS year_dim
)
ORDER BY year_dim;
+-------------------+----------+
| M_ACCOUNT_BALANCE | YEAR_DIM |
|-------------------+----------|
| 210 | 2024 |
| 510 | 2025 |
+-------------------+----------+
쿼리 처리 중에 행은 비가산 차원으로 정렬되고, 마지막 행(값의 최신 스냅샷)의 값이 집계되어 메트릭이 계산돼요.
참고: 엔진은 비가산 차원으로 행을 정렬한 다음 각 파티션에 대해 정렬 순서의 마지막 값을 검색해요. 기본 오름차순 정렬(ASC)에서는 마지막 값이 시간 기반 차원의 최신 값이에요. 내림차순 정렬(DESC)에서는 마지막 값이 가장 이른 값이에요.
ORDER BY 절에서 열을 지정하는 순서와 유사하게 차원을 지정하는 순서도 중요해요.
비가산 차원의 정렬 순서 지정하기
예시에서 보여주듯이 이 메트릭은 기간이 끝날 때 각 고객의 당좌 및 저축 잔액 값을 집계해요. 기본 정렬 순서는 오름차순(ASC)이며, 이는 엔진이 오름차순의 마지막 값, 즉 시간 기반 차원의 최신 값을 검색한다는 뜻이에요.
가장 이른 값을 검색하려면 DESC를 지정해요. 내림차순 정렬에서는 정렬 순서의 마지막 값이 가장 이른 시점이에요. 예를 들어:
METRICS (
bank_accounts.m_account_balance
NON ADDITIVE BY (year_dim DESC, month_dim DESC, day_dim DESC)
AS SUM(balance)
);
이 예시에서 DESC가 지정되었으므로 엔진은 날짜 차원을 내림차순으로 정렬하고 마지막 값(가장 이른 날짜)을 검색해요. 이 메트릭은 각 파티션에서 가장 이른 날짜의 계좌 잔액 합으로 계산돼요.
차원에 NULL 값이 포함되어 있다면 NULLS FIRST 또는 NULLS LAST 키워드를 사용해 결과에서 NULL 값을 처음 또는 마지막으로 정렬할지 지정할 수 있어요:
METRICS (
bank_accounts.m_account_balance
NON ADDITIVE BY (
year_dim DESC NULLS FIRST,
month_dim DESC NULLS FIRST,
day_dim DESC NULLS FIRST
)
AS SUM(balance)
팩트나 메트릭을 비공개로 표시하기
시맨틱 뷰의 계산에만 사용하려고 팩트나 메트릭을 정의하고, 그 팩트나 메트릭이 쿼리에서 반환되는 것을 원하지 않는다면 PRIVATE 키워드를 지정해 팩트나 메트릭을 비공개로 표시할 수 있어요. 예를 들어:
FACTS (
PRIVATE my_private_fact AS ...
)
METRICS (
PRIVATE my_private_metric AS ...
)
참고: 차원은 비공개로 표시할 수 없어요. 차원은 항상 공개예요.
비공개 팩트나 메트릭이 있는 시맨틱 뷰를 쿼리할 때 다음 절에서는 비공개 팩트나 메트릭을 지정할 수 없어요:
- SELECT 목록
- SEMANTIC_VIEW 절의 FACTS
- SEMANTIC_VIEW 절의 METRICS
- METRICS
- SELECT 문 또는 SEMANTIC_VIEW 절의 WHERE
일부 명령어와 함수는 비공개 팩트와 메트릭을 포함해요:
- 비공개 팩트와 메트릭은 DESCRIBE SEMANTIC VIEW 명령어의 출력에 나타나요. 비공개 팩트와 메트릭의 행에는
access_modifier열에PRIVATE가 표시돼요. - 비공개 팩트와 메트릭은 GET_DDL 함수 호출의 반환 값에 나열돼요. 시맨틱 뷰에 대한 SQL 문 가져오기에서 언급한 바와 같아요.
일부 명령어와 함수는 특정 조건에서만 비공개 팩트와 메트릭을 포함해요:
- INFORMATION_SCHEMA의 SEMANTIC_FACTS 및 SEMANTIC_METRICS 뷰에는 시맨틱 뷰에 대한 REFERENCES 또는 OWNERSHIP 권한이 부여된 역할을 사용하는 경우에만 비공개 팩트와 메트릭이 나열돼요.
- 그 외에는 이 뷰들은 공개 팩트와 메트릭만 나열해요.
다른 명령어와 함수는 비공개 팩트와 메트릭을 포함하지 않아요:
- 비공개 팩트는 SHOW SEMANTIC FACTS 명령어의 출력에 나타나지 않아요.
- 비공개 메트릭은 SHOW SEMANTIC METRICS 명령어의 출력에 나타나지 않아요.
매개변수화된 시맨틱 뷰에 대한 변수 정의하기
변수를 사용해 팩트, 차원, 메트릭을 매개변수화할 수 있어요. 전체 문서와 예시는 시맨틱 뷰에서 변수 사용하기를 참고해요.
역할 놀이 테이블(role-playing tables) 사용하기
하나의 물리적 테이블이 서로 다른 별칭으로 시맨틱 뷰에 여러 번 나타나며 서로 다른 역할을 모델링할 수 있어요. 이는 같은 조회 테이블(예: region 또는 date 테이블)을 서로 다른 관점에서 조인해야 할 때 유용해요:
CREATE SEMANTIC VIEW regional_analysis
TABLES (
customer_region AS my_db.my_schema.region
PRIMARY KEY (r_regionkey)
COMMENT = 'Region for customers',
supplier_region AS my_db.my_schema.region
PRIMARY KEY (r_regionkey)
COMMENT = 'Region for suppliers',
customer_nation AS my_db.my_schema.nation
PRIMARY KEY (n_nationkey),
supplier_nation AS my_db.my_schema.nation
PRIMARY KEY (n_nationkey)
)
RELATIONSHIPS (
customer_nation (n_regionkey) REFERENCES customer_region,
supplier_nation (n_regionkey) REFERENCES supplier_region
)
DIMENSIONS (
customer_region.cust_region_name AS r_name,
supplier_region.supp_region_name AS r_name
)
각 별칭은 고유한 차원, 팩트, 관계를 가질 수 있는 독립적인 논리적 테이블을 만들어요.
브리지 테이블로 다대다 관계 모델링하기
다대다(many-to-many) 관계는 브리지(교차) 테이블에서 두 엔티티 테이블로의 두 관계를 정의해 표현해요. 시스템은 관계 그래프에서 다대다 경로를 추론하고 팬아웃(fanout) 이중 계산을 방지하기 위해 중복 제거를 자동으로 처리해요:
CREATE SEMANTIC VIEW library_sv
TABLES (
authors AS my_db.my_schema.authors
PRIMARY KEY (author_id),
books AS my_db.my_schema.books
PRIMARY KEY (book_id),
book_authors AS my_db.my_schema.book_authors
PRIMARY KEY (book_id, author_id)
)
RELATIONSHIPS (
book_authors (author_id) REFERENCES authors (author_id),
book_authors (book_id) REFERENCES books (book_id)
)
DIMENSIONS (
books.category AS category,
authors.author_name AS author_name
)
METRICS (
books.total_pages AS SUM(page_count),
authors.total_revenue AS SUM(author_revenue)
)
테이블 간 차원 참조 정의하기
DDL에서는 한 테이블의 차원이 (관계 경로를 통해) 관련 테이블에 정의된 차원을 참조할 수 있어요. 이렇게 하면 표현식을 반복하지 않고도 참조하는 테이블에서 관련 테이블의 속성을 직접 노출할 수 있어요:
DIMENSIONS (
nation.d_nation_name AS n_name,
region.d_region_name AS r_name,
customer.d_customer_region AS region.d_region_name,
customer.d_customer_nation AS nation.d_nation_name
)
이 예시에서 customer.d_customer_region은 열 표현식을 반복하는 대신 region.d_region_name으로 정의돼요. 시스템은 customer에서 region으로의 관계 경로를 따라가며 값을 해석해요.
참고: 테이블 간 차원 참조는 DDL 전용 기능이에요. YAML 사양에서는 사용할 수 없어요.
차원과 팩트에서 윈도우 함수 사용하기
차원과 팩트는 순위, 누적 계산, lag/lead 값에 대한 윈도우 함수 표현식을 지원해요:
DIMENSIONS (
sales.category_rank AS DENSE_RANK() OVER (
PARTITION BY quarter, customer_segment
ORDER BY revenue DESC
),
sales.units_rank AS ROW_NUMBER() OVER (ORDER BY units_sold),
sales.prev_subcategory AS COALESCE(
LAG (subcategory, 1) OVER (PARTITION BY quarter ORDER BY id),
'missing data'
),
sales.rolling_avg_revenue AS AVG(revenue) OVER (
PARTITION BY category, segment
ORDER BY quarter
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW
)
)
FACTS (
sales.total_units AS SUM(units_sold) OVER (),
sales.revenue_by_category AS SUM(revenue) OVER (PARTITION BY category),
orders.custkey_if_many_orders AS
CASE
WHEN COUNT(*) OVER (
PARTITION BY o_custkey, DATE_TRUNC('QUARTER', o_orderdate)
) > 1
THEN o_custkey
END
)
윈도우 함수를 사용하는 메트릭의 경우 PARTITION BY EXCLUDING 구문은 지정된 차원을 제외한 모든 선택된 차원으로 파티션을 나눠요:
METRICS (
sales.credits_7day_avg AS AVG(total_credits) OVER (
PARTITION BY EXCLUDING time_spine.date_dimension
ORDER BY time_spine.date_dimension
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
),
store_sales.running_total AS SUM(store_sales.sales_amount) OVER (
PARTITION BY EXCLUDING date_dim.day
ORDER BY date_dim.day
)
)
Cortex Analyst에 사용자 지정 지침 제공하기
시맨틱 뷰에서는 다음을 설명하는 Cortex Analyst용 지침을 제공할 수 있어요:
- SQL 문 생성 방법
- 질문 분류 및 추가 정보 요청 방법
이 사용자 지정 지침을 제공하려면 다음 절을 사용해요:
- SQL 문 생성 방법에 대한 지침은 CREATE SEMANTIC VIEW 명령어의 AI_SQL_GENERATION 절을 사용해요.
- 예를 들어 모든 숫자 열이 소수점 둘째 자리로 반올림되도록 Cortex Analyst가 SQL 문을 생성하게 하려면 다음을 지정해요:
CREATE SEMANTIC VIEW my_semantic_view ... -- Definitions of logical tables, relationships, dimensions, facts, and metrics ... AI_SQL_GENERATION 'Ensure that all numeric columns are rounded to 2 decimal points.' ... -- Additional clauses
- 예를 들어 모든 숫자 열이 소수점 둘째 자리로 반올림되도록 Cortex Analyst가 SQL 문을 생성하게 하려면 다음을 지정해요:
- 질문 분류 방법에 대한 지침은 AI_QUESTION_CATEGORIZATION 절을 사용해요.
- 예를 들어 사용자에 대한 질문을 거부하도록 Cortex Analyst에 지시하려면 다음을 지정해요:
CREATE SEMANTIC VIEW my_semantic_view ... -- Definitions of logical tables, relationships, dimensions, facts, and metrics ... AI_QUESTION_CATEGORIZATION 'Reject all questions asking about users. Ask users to contact their admin.' ... -- Additional clauses
- 예를 들어 사용자에 대한 질문을 거부하도록 Cortex Analyst에 지시하려면 다음을 지정해요:
질문이 명확하지 않은 경우 더 많은 세부 정보를 요청하는 지침도 제공할 수 있어요. 예를 들어:
AI_QUESTION_CATEGORIZATION 'If the question asks for users without providing a product_type, consider this question UNCLEAR and ask the user to specify product_type.'
참고: Cortex Agent를 통해 Cortex Analyst를 사용할 때 에이전트는 사용자 지정 지침을 직접 따르며
UNCLEAR같은 특정 상태 키워드를 요구하지 않아요. 질문 분류 지침을 자연어로 작성할 수 있어요. 자세한 내용은 Cortex Agents를 통한 사용자 지정 지침을 참고해요.
시맨틱 뷰에 대한 검증된 쿼리 제공하기
Cortex Analyst에서는 시맨틱 뷰에 대한 검증된 쿼리(verified queries)를 제공해 결과의 정확성과 신뢰성을 높일 수 있어요.
시맨틱 뷰를 만들 때 뷰에 대한 검증된 쿼리를 지정할 수 있어요. CREATE SEMANTIC VIEW 명령어에서 AI_VERIFIED_QUERIES 절을 사용해 검증된 쿼리를 지정해요. 이 절은 COMMENT 절 뒤, COPY GRANTS 절 앞에 지정해요.
이 절에서 하나 이상의 검증된 쿼리를 지정해요:
AI_VERIFIED_QUERIES (
<verified_query_name> AS (
QUESTION '<question>'
VERIFIED_AT <timestamp>
ONBOARDING_QUESTION <boolean>
VERIFIED_BY '(<purpose> = <contact>)'
SQL '<verified_query>'
)
[, ...]
)
각 검증된 쿼리에 대해 다음 절을 지정해요:
- QUESTION: 기대되는 쿼리를 만들어내는 질문
- VERIFIED_AT: 쿼리가 검증된 타임스탬프 (Unix epoch 이후 초 단위)
- ONBOARDING_QUESTION: 질문이 온보딩 질문이어야 하는지 여부를 나타내는 TRUE(온보딩 질문이란 Cortex Analyst로 구동되는 앱과 상호작용하는 사용자에게 제안되어야 하는 질문)
- VERIFIED_BY: 쿼리가 질문에 답한다고 검증한 담당자의 목적과 이름
- SQL: 질문에 답하는 쿼리에 대한 SQL 문
다음 예시는 시맨틱 뷰를 만들고 total_discounted_price라는 검증된 쿼리를 시맨틱 뷰에 추가해요:
CREATE OR REPLACE SEMANTIC VIEW tpch_rev_analysis
...
COMMENT = 'Semantic view for revenue analysis'
AI_VERIFIED_QUERIES (
total_discounted_price AS (
QUESTION 'What is the average order value for each year?'
VERIFIED_AT 1772645863
ONBOARDING_QUESTION TRUE
VERIFIED_BY '(STEWARD = data_stewards)'
SQL 'SELECT
o.order_year,
MIN(o.order_date) AS start_date,
MAX(o.order_date) AS end_date,
AVG(o.o_totalprice) AS avg_order_value
FROM orders AS o
GROUP BY o.order_year
ORDER BY o.order_year DESC NULLS LAST'
)
);
AI_VERIFIED_QUERIES 절에 대한 자세한 내용은 다음 섹션을 참고해요:
- CREATE SEMANTIC VIEW 명령어의 구문
- 검증된 쿼리의 구문
- 검증된 쿼리의 매개변수 설명
YAML 사양에서 시맨틱 뷰 만들기
YAML 사양에서 시맨틱 뷰를 만들려면 SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML 저장 프로시저를 호출할 수 있어요.
먼저 세 번째 인수로 TRUE를 전달해 YAML 사양에서 시맨틱 뷰를 만들 수 있는지 검증해요.
다음 예시는 주어진 시맨틱 모델 사양을 YAML로 사용해 my_db 데이터베이스와 my_schema 스키마에 tpch_analysis라는 시맨틱 뷰를 만들 수 있는지 검증해요:
CALL SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML (
'my_db.my_schema',
$$
name: TPCH_REV_ANALYSIS
description: Semantic view for revenue analysis
tables:
- name: CUSTOMERS
description: Main table for customer data
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: CUSTOMER
primary_key:
columns:
- C_CUSTKEY
dimensions:
- name: CUSTOMER_NAME
synonyms:
- customer name
description: Name of the customer
expr: customers.c_name
data_type: VARCHAR(25)
- name: C_CUSTKEY
expr: C_CUSTKEY
data_type: VARCHAR(134217728)
metrics:
- name: CUSTOMER_COUNT
description: Count of number of customers
expr: COUNT(c_custkey)
- name: LINE_ITEMS
description: Line items in orders
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: LINEITEM
primary_key:
columns:
- L_ORDERKEY
- L_LINENUMBER
dimensions:
- name: L_ORDERKEY
expr: L_ORDERKEY
data_type: VARCHAR(134217728)
- name: L_LINENUMBER
expr: L_LINENUMBER
data_type: VARCHAR(134217728)
facts:
- name: DISCOUNTED_PRICE
description: Extended price after discount
expr: l_extendedprice * (1 - l_discount)
data_type: "NUMBER(25,4)"
- name: LINE_ITEM_ID
expr: "CONCAT(l_orderkey, '-', l_linenumber)"
data_type: VARCHAR(134217728)
- name: ORDERS
synonyms:
- sales orders
description: All orders table for the sales domain
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: ORDERS
primary_key:
columns:
- O_ORDERKEY
dimensions:
- name: ORDER_DATE
description: Date when the order was placed
expr: o_orderdate
data_type: DATE
- name: ORDER_YEAR
description: Year when the order was placed
expr: YEAR(o_orderdate)
data_type: "NUMBER(4,0)"
- name: O_ORDERKEY
expr: O_ORDERKEY
data_type: VARCHAR(134217728)
- name: O_CUSTKEY
expr: O_CUSTKEY
data_type: VARCHAR(134217728)
facts:
- name: COUNT_LINE_ITEMS
expr: COUNT(line_items.line_item_id)
data_type: "NUMBER(18,0)"
metrics:
- name: AVERAGE_LINE_ITEMS_PER_ORDER
description: Average number of line items per order
expr: AVG(orders.count_line_items)
- name: ORDER_AVERAGE_VALUE
description: Average order value across all orders
expr: AVG(orders.o_totalprice)
relationships:
- name: LINE_ITEM_TO_ORDERS
left_table: LINE_ITEMS
right_table: ORDERS
relationship_columns:
- left_column: L_ORDERKEY
right_column: O_ORDERKEY
relationship_type: many_to_one
- name: ORDERS_TO_CUSTOMERS
left_table: ORDERS
right_table: CUSTOMERS
relationship_columns:
- left_column: O_CUSTKEY
right_column: C_CUSTKEY
relationship_type: many_to_one
$$,
TRUE
);
사양이 유효하면 저장 프로시저는 다음 메시지를 반환해요:
+----------------------------------------------------------------------------------+
| SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML |
|----------------------------------------------------------------------------------|
| YAML file is valid for creating a semantic view. No object has been created yet. |
+----------------------------------------------------------------------------------+
YAML 구문이 유효하지 않으면 저장 프로시저는 예외를 던져요. 예를 들어 콜론이 누락된 경우:
relationships
- name: LINE_ITEM_TO_ORDERS
저장 프로시저는 YAML 구문이 유효하지 않다는 것을 나타내는 예외를 던져요:
392400 (22023): Uncaught exception of type 'EXPRESSION_ERROR' on line 3 at position 23:
Invalid semantic model YAML: while scanning a simple key
in 'reader', line 90, column 3:
relationships
^
could not find expected ':'
in 'reader', line 91, column 11:
- name: LINE_ITEM_TO_ORDERS
^
사양이 존재하지 않는 물리적 테이블을 참조하면 저장 프로시저는 예외를 던져요:
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: NONEXISTENT
002003 (42S02): Uncaught exception of type 'EXPRESSION_ERROR' on line 3 at position 23:
SQL compilation error:
Table 'SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.NONEXISTENT' does not exist or not authorized.
마찬가지로 사양이 존재하지 않는 기본 키 열을 참조하면 저장 프로시저는 예외를 던져요:
primary_key:
columns:
- NONEXISTENT
000904 (42000): Uncaught exception of type 'EXPRESSION_ERROR' on line 3 at position 23:
SQL compilation error: error line 0 at position -1
invalid identifier 'NONEXISTENT'
그런 다음 세 번째 인수를 전달하지 않고 저장 프로시저를 호출해 시맨틱 뷰를 만들 수 있어요.
다음 예시는 my_db 데이터베이스와 my_schema 스키마에 tpch_analysis라는 시맨틱 뷰를 만들어요:
CALL SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML (
'my_db.my_schema',
$$
name: TPCH_REV_ANALYSIS
description: Semantic view for revenue analysis
tables:
- name: CUSTOMERS
description: Main table for customer data
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: CUSTOMER
primary_key:
columns:
- C_CUSTKEY
dimensions:
- name: CUSTOMER_NAME
synonyms:
- customer name
description: Name of the customer
expr: customers.c_name
data_type: VARCHAR(25)
- name: C_CUSTKEY
expr: C_CUSTKEY
data_type: VARCHAR(134217728)
metrics:
- name: CUSTOMER_COUNT
description: Count of number of customers
expr: COUNT(c_custkey)
- name: LINE_ITEMS
description: Line items in orders
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: LINEITEM
primary_key:
columns:
- L_ORDERKEY
- L_LINENUMBER
dimensions:
- name: L_ORDERKEY
expr: L_ORDERKEY
data_type: VARCHAR(134217728)
- name: L_LINENUMBER
expr: L_LINENUMBER
data_type: VARCHAR(134217728)
facts:
- name: DISCOUNTED_PRICE
description: Extended price after discount
expr: l_extendedprice * (1 - l_discount)
data_type: "NUMBER(25,4)"
- name: LINE_ITEM_ID
expr: "CONCAT(l_orderkey, '-', l_linenumber)"
data_type: VARCHAR(134217728)
- name: ORDERS
synonyms:
- sales orders
description: All orders table for the sales domain
base_table:
database: SNOWFLAKE_SAMPLE_DATA
schema: TPCH_SF1
table: ORDERS
primary_key:
columns:
- O_ORDERKEY
dimensions:
- name: ORDER_DATE
description: Date when the order was placed
expr: o_orderdate
data_type: DATE
- name: ORDER_YEAR
description: Year when the order was placed
expr: YEAR(o_orderdate)
data_type: "NUMBER(4,0)"
- name: O_ORDERKEY
expr: O_ORDERKEY
data_type: VARCHAR(134217728)
- name: O_CUSTKEY
expr: O_CUSTKEY
data_type: VARCHAR(134217728)
facts:
- name: COUNT_LINE_ITEMS
expr: COUNT(line_items.line_item_id)
data_type: "NUMBER(18,0)"
metrics:
- name: AVERAGE_LINE_ITEMS_PER_ORDER
description: Average number of line items per order
expr: AVG(orders.count_line_items)
- name: ORDER_AVERAGE_VALUE
description: Average order value across all orders
expr: AVG(orders.o_totalprice)
relationships:
- name: LINE_ITEM_TO_ORDERS
left_table: LINE_ITEMS
right_table: ORDERS
relationship_columns:
- left_column: L_ORDERKEY
right_column: O_ORDERKEY
relationship_type: many_to_one
- name: ORDERS_TO_CUSTOMERS
left_table: ORDERS
right_table: CUSTOMERS
relationship_columns:
- left_column: O_CUSTKEY
right_column: C_CUSTKEY
relationship_type: many_to_one
$$
);
+-----------------------------------------+
| SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML |
|-----------------------------------------|
| Semantic view was successfully created. |
+-----------------------------------------+
기존 시맨틱 뷰의 주석 수정하기
기존 시맨틱 뷰의 주석을 수정하려면 ALTER SEMANTIC VIEW 명령어를 실행해요. 예를 들어:
ALTER SEMANTIC VIEW my_semantic_view SET COMMENT = 'my comment';
참고: ALTER SEMANTIC VIEW 명령어로는 주석 외의 속성을 변경할 수 없어요. 시맨틱 뷰의 다른 속성을 변경하려면 CREATE OR ALTER SEMANTIC VIEW를 사용하거나 시맨틱 뷰를 교체해요. 기존 시맨틱 뷰 교체하기를 참고해요.
시맨틱 뷰의 주석을 설정하는 데 COMMENT 명령어를 사용할 수도 있어요:
COMMENT ON SEMANTIC VIEW my_semantic_view IS 'my comment';
시맨틱 뷰 만들기 또는 변경하기
시맨틱 뷰가 없다면 만들고, 기존 시맨틱 뷰를 새 정의와 일치하도록 변경하려면 CREATE OR ALTER SEMANTIC VIEW를 사용해요.
시맨틱 뷰를 CREATE OR REPLACE로 교체하는 것과 달리 CREATE OR ALTER는 COPY GRANTS 없이 시맨틱 뷰의 기존 권한 부여를 보존해요. 시맨틱 뷰가 이미 정의와 일치하면 변경되지 않고 유지돼요.
예를 들어:
CREATE OR ALTER SEMANTIC VIEW tpch_rev_analysis
TABLES (
orders AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.ORDERS
PRIMARY KEY (o_orderkey)
WITH SYNONYMS ('sales orders')
COMMENT = 'All orders table for the sales domain',
customers AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.CUSTOMER
PRIMARY KEY (c_custkey)
COMMENT = 'Main table for customer data',
line_items AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.LINEITEM
PRIMARY KEY (l_orderkey, l_linenumber)
COMMENT = 'Line items in orders'
)
RELATIONSHIPS (
orders_to_customers AS
orders (o_custkey) REFERENCES customers,
line_item_to_orders AS
line_items (l_orderkey) REFERENCES orders
)
FACTS (
line_items.line_item_id AS CONCAT(l_orderkey, '-', l_linenumber),
orders.count_line_items AS COUNT(line_items.line_item_id),
line_items.discounted_price AS l_extendedprice * (1 - l_discount)
COMMENT = 'Extended price after discount'
)
DIMENSIONS (
customers.customer_name AS customers.c_name
WITH SYNONYMS = ('customer name')
COMMENT = 'Name of the customer',
orders.order_date AS o_orderdate
COMMENT = 'Date when the order was placed',
orders.order_year AS YEAR(o_orderdate)
COMMENT = 'Year when the order was placed'
)
METRICS (
customers.customer_count AS COUNT(c_custkey)
COMMENT = 'Count of number of customers',
orders.order_average_value AS AVG(orders.o_totalprice)
COMMENT = 'Average order value across all orders',
orders.average_line_items_per_order AS AVG(orders.count_line_items)
COMMENT = 'Average number of line items per order'
)
COMMENT = 'Semantic view for revenue analysis';
참고: CREATE OR ALTER SEMANTIC VIEW는 시맨틱 뷰나 시맨틱 뷰 안의 테이블, 팩트, 차원, 메트릭에 태그를 추가하거나 변경하는 것을 지원하지 않아요. 기존 태그는 보존돼요.
자세한 내용은 CREATE OR ALTER SEMANTIC VIEW 구문과 CREATE OR ALTER <object>를 참고해요.
기존 시맨틱 뷰 교체하기
기존 시맨틱 뷰를 교체하려면(예: 뷰의 정의를 변경하려면) CREATE SEMANTIC VIEW를 실행할 때 OR REPLACE를 지정해요. 기존 시맨틱 뷰에 부여된 권한을 보존하려면 COPY GRANTS를 지정해요. 예를 들어:
CREATE OR REPLACE SEMANTIC VIEW tpch_rev_analysis
TABLES (
orders AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.ORDERS
PRIMARY KEY (o_orderkey)
WITH SYNONYMS ('sales orders')
COMMENT = 'All orders table for the sales domain',
customers AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.CUSTOMER
PRIMARY KEY (c_custkey)
COMMENT = 'Main table for customer data',
line_items AS SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.LINEITEM
PRIMARY KEY (l_orderkey, l_linenumber)
COMMENT = 'Line items in orders'
)
RELATIONSHIPS (
orders_to_customers AS
orders (o_custkey) REFERENCES customers,
line_item_to_orders AS
line_items (l_orderkey) REFERENCES orders
)
FACTS (
line_items.line_item_id AS CONCAT(l_orderkey, '-', l_linenumber),
orders.count_line_items AS COUNT(line_items.line_item_id),
line_items.discounted_price AS l_extendedprice * (1 - l_discount)
COMMENT = 'Extended price after discount'
)
DIMENSIONS (
customers.customer_name AS customers.c_name
WITH SYNONYMS = ('customer name')
COMMENT = 'Name of the customer',
orders.order_date AS o_orderdate
COMMENT = 'Date when the order was placed',
orders.order_year AS YEAR(o_orderdate)
COMMENT = 'Year when the order was placed'
)
METRICS (
customers.customer_count AS COUNT(c_custkey)
COMMENT = 'Count of number of customers',
orders.order_average_value AS AVG(orders.o_totalprice)
COMMENT = 'Average order value across all orders',
orders.average_line_items_per_order AS AVG(orders.count_line_items)
COMMENT = 'Average number of line items per order'
)
COMMENT = 'Semantic view for revenue analysis and different comment'
COPY GRANTS;
시맨틱 뷰 나열하기
현재 스키마 또는 지정된 스키마의 시맨틱 뷰를 나열하려면 SHOW SEMANTIC VIEWS 명령어를 실행해요. 예를 들어:
SHOW SEMANTIC VIEWS;
+-------------------------------+-----------------------+---------------+-------------------+----------------------------------------------+-----------------+-----------------+-----------+
| created_on | name | database_name | schema_name | comment | owner | owner_role_type | extension |
|-------------------------------+-----------------------+---------------+-------------------+----------------------------------------------+-----------------+-----------------+-----------|
| 2025-03-20 15:06:34.039 -0700 | MY_NEW_SEMANTIC_MODEL | MY_DB | MY_SCHEMA | A semantic model created through the wizard. | MY_ROLE | ROLE | ["CA"] |
| 2025-02-28 16:16:04.002 -0800 | O_TPCH_SEMANTIC_VIEW | MY_DB | MY_SCHEMA | NULL | MY_ROLE | ROLE | NULL |
| 2025-03-21 07:03:54.120 -0700 | TPCH_REV_ANALYSIS | MY_DB | MY_SCHEMA | Semantic view for revenue analysis | MY_ROLE | ROLE | NULL |
+-------------------------------+-----------------------+---------------+-------------------+----------------------------------------------+-----------------+-----------------+-----------+
SHOW OBJECTS 명령어의 출력에는 시맨틱 뷰가 포함돼요. kind 열에서 객체 유형은 VIEW로 나열돼요. 예를 들어:
SHOW OBJECTS LIKE '%TPCH_ANALYSIS%' IN SCHEMA;
+-------------------------------+---------------+---------------+-------------+------+---------+------------+------+-------+---------+----------------+-----------------+-----------+------------+------------+
| created_on | name | database_name | schema_name | kind | comment | cluster_by | rows | bytes | owner | retention_time | owner_role_type | is_hybrid | is_dynamic | is_iceberg |
|-------------------------------+---------------+---------------+-------------+------+---------+------------+------+-------+---------+----------------+-----------------+-----------+------------+------------|
| 2025-10-03 16:28:01.505 -0700 | TPCH_ANALYSIS | MY_DB | MY_SCHEMA | VIEW | | | 0 | 0 | MY_ROLE | 1 | ROLE | N | N | N |
+-------------------------------+---------------+---------------+-------------+------+---------+------------+------+-------+---------+----------------+-----------------+-----------+------------+------------+
ACCOUNT_USAGE 및 INFORMATION_SCHEMA 스키마의 시맨틱 뷰용 뷰를 쿼리할 수도 있어요.
차원, 팩트, 메트릭 나열하기
뷰, 스키마, 데이터베이스 또는 계정에서 사용 가능한 차원, 팩트, 메트릭을 나열하려면 다음 명령어를 실행할 수 있어요:
- SHOW SEMANTIC DIMENSIONS
- SHOW SEMANTIC FACTS
- SHOW SEMANTIC METRICS
기본적으로 이 명령어들은 현재 스키마에 정의된 시맨틱 뷰에서 사용 가능한 차원, 팩트, 메트릭을 나열해요:
SHOW SEMANTIC DIMENSIONS;
+---------------+-------------+--------------------+------------+---------------+--------------+-------------------+--------------------------------+
| database_name | schema_name | semantic_view_name | table_name | name | data_type | synonyms | comment |
|---------------+-------------+--------------------+------------+---------------+--------------+-------------------+--------------------------------|
| MY_DB | MY_SCHEMA | TPCH_REV_ANALYSIS | CUSTOMERS | CUSTOMER_NAME | VARCHAR(25) | ["customer name"]| Name of the customer |
| MY_DB | MY_SCHEMA | TPCH_REV_ANALYSIS | CUSTOMERS | C_CUSTKEY | NUMBER(38,0) | NULL | NULL |
...
SHOW SEMANTIC FACTS;
+---------------+-------------+--------------------+------------+------------------+--------------------+----------+-------------------------------+
| database_name | schema_name | semantic_view_name | table_name | name | data_type | synonyms | comment |
|---------------+-------------+--------------------+------------+------------------+--------------------+----------+-------------------------------|
| MY_DB | MY_SCHEMA | TPCH_REV_ANALYSIS | LINE_ITEMS | DISCOUNTED_PRICE | NUMBER(25,4) | NULL | Extended price after discount |
| MY_DB | MY_SCHEMA | TPCH_REV_ANALYSIS | LINE_ITEMS | LINE_ITEM_ID | VARCHAR(134217728) | NULL | NULL |
...
SHOW SEMANTIC METRICS;
+---------------+-------------+--------------------+------------+------------------------------+--------------+----------+----------------------------------------+
| database_name | schema_name | semantic_view_name | table_name | name | data_type | synonyms | comment |
|---------------+-------------+--------------------+------------+------------------------------+--------------+----------+----------------------------------------|
| MY_DB | MY_SCHEMA | TPCH_REV_ANALYSIS | CUSTOMERS | CUSTOMER_COUNT | NUMBER(18,0) | NULL | Count of number of customers |
| MY_DB | MY_SCHEMA | TPCH_REV_ANALYSIS | ORDERS | AVERAGE_LINE_ITEMS_PER_ORDER | NUMBER(36,6) | NULL | Average number of line items per order |
...
다음 예시들은 서로 다른 범위 내의 시맨틱 뷰에 대한 차원, 팩트, 메트릭을 나열하는 방법을 보여줘요:
- 현재 데이터베이스의 시맨틱 뷰에서 차원, 팩트, 메트릭 나열하기:
SHOW SEMANTIC DIMENSIONS IN DATABASE; SHOW SEMANTIC FACTS IN DATABASE; SHOW SEMANTIC METRICS IN DATABASE; - 특정 스키마 또는 데이터베이스의 시맨틱 뷰에서 차원, 팩트, 메트릭 나열하기:
SHOW SEMANTIC DIMENSIONS IN SCHEMA my_db.my_other_schema; SHOW SEMANTIC DIMENSIONS IN DATABASE my_db; SHOW SEMANTIC FACTS IN SCHEMA my_db.my_other_schema; SHOW SEMANTIC FACTS IN DATABASE my_db; SHOW SEMANTIC METRICS IN SCHEMA my_db.my_other_schema; SHOW SEMANTIC METRICS IN DATABASE my_db; - 계정의 시맨틱 뷰에서 차원, 팩트, 메트릭 나열하기:
SHOW SEMANTIC DIMENSIONS IN ACCOUNT; SHOW SEMANTIC FACTS IN ACCOUNT; SHOW SEMANTIC METRICS IN ACCOUNT; - 특정 시맨틱 뷰에서 차원, 팩트, 메트릭 나열하기:
SHOW SEMANTIC DIMENSIONS IN my_semantic_view; SHOW SEMANTIC FACTS IN my_semantic_view; SHOW SEMANTIC METRICS IN my_semantic_view;
시맨틱 뷰를 쿼리한다면 SHOW SEMANTIC DIMENSIONS FOR METRIC 명령어를 사용해 특정 메트릭을 지정할 때 반환할 수 있는 차원을 확인할 수 있어요. 자세한 내용은 주어진 메트릭에 대해 반환할 수 있는 차원 선택하기를 참고해요.
시맨틱 뷰에 대해 SHOW COLUMNS 명령어를 실행하면 출력에 시맨틱 뷰의 차원, 팩트, 메트릭이 포함돼요. kind 열은 행이 차원, 팩트 또는 메트릭을 나타내는지 표시해요.
예를 들어:
SHOW COLUMNS IN VIEW my_db.my_schema.tpch_analysis;
+---------------+-------------+------------------------------+-----------------------------------------------------------------------------------------+----------+---------+-----------+------------+---------+---------------+---------------+-------------------------+
| table_name | schema_name | column_name | data_type | null? | default | kind | expression | comment | database_name| autoincrement | schema_evolution_record |
|---------------+-------------+------------------------------+-----------------------------------------------------------------------------------------+----------+---------+-----------+------------+---------+---------------+---------------+-------------------------|
| TPCH_ANALYSIS | MY_SCHEMA | CUSTOMER_COUNT | {"type":"FIXED","precision":18,"scale":0,"nullable":false} | NOT_NULL | | METRIC | | | MY_DB | | NULL |
| TPCH_ANALYSIS | MY_SCHEMA | CUSTOMER_COUNTRY_CODE | {"type":"TEXT","length":15,"byteLength":60,"nullable":true,"fixed":false} | true | | DIMENSION | | | MY_DB | | NULL |
...
시맨틱 뷰에 대한 세부 정보 보기
시맨틱 뷰의 세부 정보를 보려면 DESCRIBE SEMANTIC VIEW 명령어를 실행해요. 예를 들어:
DESCRIBE SEMANTIC VIEW tpch_rev_analysis;
+--------------+------------------------------+---------------+--------------------------+----------------------------------------+
| object_kind | object_name | parent_entity | property | property_value |
|--------------+------------------------------+---------------+--------------------------+----------------------------------------|
| NULL | NULL | NULL | COMMENT | Semantic view for revenue analysis |
| TABLE | CUSTOMERS | NULL | BASE_TABLE_DATABASE_NAME | SNOWFLAKE_SAMPLE_DATA |
| TABLE | CUSTOMERS | NULL | BASE_TABLE_SCHEMA_NAME | TPCH_SF1 |
| TABLE | CUSTOMERS | NULL | BASE_TABLE_NAME | CUSTOMER |
| TABLE | CUSTOMERS | NULL | PRIMARY_KEY | ["C_CUSTKEY"] |
| TABLE | CUSTOMERS | NULL | COMMENT | Main table for customer data |
| DIMENSION | CUSTOMER_NAME | CUSTOMERS | TABLE | CUSTOMERS |
| DIMENSION | CUSTOMER_NAME | CUSTOMERS | EXPRESSION | customers.c_name |
...
시맨틱 뷰에 대한 SQL 문 가져오기
GET_DDL 함수를 호출해 시맨틱 뷰를 만든 DDL 문을 검색할 수 있어요.
참고: 시맨틱 뷰에 대해 이 함수를 호출하려면 시맨틱 뷰에 대한 REFERENCES 또는 OWNERSHIP 권한이 부여된 역할을 사용해야 해요.
GET_DDL을 호출할 때 객체 유형으로 'SEMANTIC_VIEW'를 전달해요. 예를 들어:
SELECT GET_DDL('SEMANTIC_VIEW', 'tpch_rev_analysis', TRUE);
+-----------------------------------------------------------------------------------+
| GET_DDL('SEMANTIC_VIEW', 'TPCH_REV_ANALYSIS', TRUE) |
|-----------------------------------------------------------------------------------|
| create or replace semantic view DYOSHINAGA_DB.DYOSHINAGA_SCHEMA.TPCH_REV_ANALYSIS |
| tables ( |
| ORDERS primary key (O_ORDERKEY) with synonyms=('sales orders') comment='All orders table for the sales domain', |
| CUSTOMERS as CUSTOMER primary key (C_CUSTKEY) comment='Main table for customer data', |
| LINE_ITEMS as LINEITEM primary key (L_ORDERKEY,L_LINENUMBER) comment='Line items in orders' |
| ) |
| relationships ( |
| ORDERS_TO_CUSTOMERS as ORDERS(O_CUSTKEY) references CUSTOMERS(C_CUSTKEY), |
| LINE_ITEM_TO_ORDERS as LINE_ITEMS(L_ORDERKEY) references ORDERS(O_ORDERKEY) |
| ) |
...
반환 값에는 비공개 팩트와 메트릭(PRIVATE 키워드로 표시된 팩트와 메트릭)이 포함돼요.
시맨틱 뷰에 대한 YAML 사양 가져오기
시맨틱 뷰에 대한 YAML 사양을 가져오려면 SYSTEM$READ_YAML_FROM_SEMANTIC_VIEW 함수를 호출해요.
다음 예시는 my_db 데이터베이스와 my_schema 스키마에 있는 tpch_analysis라는 시맨틱 뷰에 대한 YAML 사양을 반환해요:
SELECT SYSTEM$READ_YAML_FROM_SEMANTIC_VIEW (
'my_db.my_schema.tpch_rev_analysis'
);
+-------------------------------------------------------------+
| READ_YAML_FROM_SEMANTIC_VIEW |
|-------------------------------------------------------------|
| name: TPCH_REV_ANALYSIS |
| description: Semantic view for revenue analysis |
| tables: |
| - name: CUSTOMERS |
| description: Main table for customer data |
| base_table: |
| database: SNOWFLAKE_SAMPLE_DATA |
| schema: TPCH_SF1 |
| table: CUSTOMER |
| primary_key: |
| columns: |
| - C_CUSTKEY |
| dimensions: |
| - name: CUSTOMER_NAME |
| synonyms: |
| - customer name |
| description: Name of the customer |
| expr: customers.c_name |
| data_type: VARCHAR(25) |
...
시맨틱 뷰를 Tableau 데이터 원본(TDS) 파일로 내보내기
프리뷰 기능 — 공개됨
모든 계정에서 사용할 수 있어요.
시맨틱 뷰를 Tableau 데이터 원본(TDS) 파일로 내보내려면 SYSTEM$EXPORT_TDS_FROM_SEMANTIC_VIEW 함수를 호출해요.
다음 예시는 my_sv_for_export 시맨틱 뷰에 대한 TDS 파일 콘텐츠를 반환해요:
SELECT SYSTEM$EXPORT_TDS_FROM_SEMANTIC_VIEW ('my_sv_for_export');
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SYSTEM$EXPORT_TDS_FROM_SEMANTIC_VIEW('MY_SV_FOR_EXPORT') |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <?xml version="1.0" encoding="UTF-8"?> |
| <!--Tableau compatibility notice: |
| - Generated TDS schema version 18.1 is validated against Tableau Desktop 2025.2 |
| - Connection customization schema version 1 enables CAP_* settings to take effect. |
| - Update these versions if your Tableau client requires a different schema.--> |
| <!--Dimensions and measures with duplicated names [DUPLICATE_DIM] are not shown in the TDS file--> |
| <datasource xmlns:user="http://www.tableausoftware.com/xml/user" formatted-name="federated.0484db64fcbd48d89e8af86a62" inline="true" version="18.1"> |
| <document-format-change-manifest> |
| ... |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
XML을 .tds 파일로 복사해 Tableau Desktop에서 파일을 열어요.
Tableau Desktop은 왼쪽의 폴더 목록에 각 논리적 테이블에 대한 폴더를 표시해요. 폴더 이름은 밑줄 대신 공백을 사용하고 각 단어는 대문자로 시작해요. 예를 들어 date_dim 논리적 테이블의 폴더 이름은 Date Dim이에요.
각 폴더에는 시맨틱 뷰의 차원, 팩트, 메트릭에 해당하는 Tableau 차원과 측정값이 포함돼요.
다음 섹션에서는 변환 프로세스에 대한 더 자세한 내용과 제한 사항을 제공해요:
- 변환에 대해
- Tableau Desktop에서 시맨틱 뷰 사용 시 제한 사항
변환에 대해
이 함수는 시맨틱 뷰의 차원, 팩트, 메트릭을 Tableau TDS 파일의 다음 항목으로 변환해요:
| 시맨틱 뷰의 요소 | Tableau 등가물 (차원 또는 측정값) | 데이터가 집계되는 방법 |
|---|---|---|
| 차원 | 차원(Dimension) |
|
| 숫자 팩트 | 측정값(Measure) | SUM |
| 비숫자 팩트 | 차원(Dimension) |
|
| 숫자 메트릭 | 측정값(Measure) | TDS 파일은 메트릭 대신 계산된 필드를 사용해요. 계산된 필드는 메트릭 값을 Snowflake AGG 함수에 전달해요. |
| 비숫자 메트릭 | 차원(Dimension) |
|
| 숫자 파생 메트릭 | 측정값(Measure) | TDS 파일은 메트릭 대신 계산된 필드를 사용해요. 계산된 필드는 메트릭 값을 Snowflake AGG 함수에 전달해요. |
| 비숫자 파생 메트릭 | 차원(Dimension) |
|
다음 Snowflake 데이터 형식은 해당하는 Tableau TDS 데이터 형식으로 매핑돼요:
| Snowflake 데이터 형식 | 등가 Tableau 데이터 형식 |
|---|---|
| NUMBER/FIXED (scale이 0보다 큰 경우) | real |
| NUMBER/FIXED (scale이 0 또는 null인 경우) | integer |
| FLOAT 또는 DECFLOAT | real |
| STRING 또는 BINARY | string |
| BOOLEAN | boolean |
| TIME | time |
| DATE | date |
| DATETIME 또는 TIMESTAMP | datetime |
| GEOGRAPHY | spatial |
| 반정형(VARIANT, OBJECT, ARRAY), 정형(ARRAY, OBJECT, MAP), 비정형(FILE), GEOMETRY, UUID, VECTOR | string |
TDS 파일에는 Snowflake에 대한 연결을 위해 사용자 지정된 다음 기능(capabilities)이 있어요:
| 사용자 지정 이름 | 값 | 사용자 지정의 효과 |
|---|---|---|
CAP_ODBC_METADATA_SUPPRESS_EXECUTED_QUERY |
yes |
Tableau가 열 이름을 확인하기 위해 SELECT * FROM table WHERE 1=0 같은 쿼리를 실제로 실행하는 것을 방지해요. |
CAP_ODBC_METADATA_SUPPRESS_PREPARED_QUERY |
yes |
Tableau가 문을 "준비"(실행하지 않고 Snowflake에 보내 구문 분석)해 유형을 파악하는 것을 방지해요. |
CAP_ODBC_METADATA_SUPPRESS_SELECT_STAR |
yes |
Tableau가 메타데이터를 읽기 위해 SELECT * 쿼리를 사용하는 것을 방지해요. |
CAP_ODBC_METADATA_SUPPRESS_SQLCOLUMNS_API |
no |
Tableau가 표준 ODBC SQLColumns 함수를 활성화하고 사용해 시맨틱 뷰에 대한 열 정보를 반환하도록 강제해요. 이 열 정보에는 열 이름, 데이터 형식, 정밀도가 포함돼요. |
CAP_DISABLE_ESCAPE_UNDERSCORE_IN_CATALOG |
yes |
Tableau가 데이터베이스 이름을 검색할 때 밑줄을 이스케이프하는 것을 방지해요. |
Tableau Desktop에서 시맨틱 뷰 사용 시 제한 사항
다음 제한 사항이 Tableau Desktop의 시맨틱 뷰에 적용돼요:
- 시맨틱 뷰에서 추출(extract)을 만들 수 없어요.
- 연결을 Live에서 Extract로 변경하면 Tableau Desktop은 다음 오류와 함께 실패해요:
SQL compilation error: Requested semantic expression 'XXX' in FACTS clause must be one of the following types: (DIMENSION, FACT). Unable to create extract
- 연결을 Live에서 Extract로 변경하면 Tableau Desktop은 다음 오류와 함께 실패해요:
- 시맨틱 뷰에서 Measure Values 필드를 사용할 수 없어요.
- 시맨틱 뷰에서 Measure Values 필드를 선택하면 Tableau Desktop은 다음 오류를 보고해요:
Unable to complete action Error Code: B9F09DDB SQL compilation error: error line 1 at position 7 Invalid metric expression 'SUM(1)'.
- 시맨틱 뷰에서 Measure Values 필드를 선택하면 Tableau Desktop은 다음 오류를 보고해요:
- 시맨틱 뷰에서 Count 필드를 선택할 수 없어요.
SemanticViewName(Count)를 선택하면 Tableau Desktop은 다음 오류를 보고해요:Unable to complete action Error Code: B9F09DDB SQL compilation error: error line 1 at position 7 Invalid metric expression 'SUM(1)'.- 행 수는 쿼리에 지정된 차원, 팩트, 메트릭에 따라 달라질 수 있으므로 Tableau Desktop은 시맨틱 뷰의 행 수를 보고할 수 없어요.
- 측정값을 단독으로 끌어다 놓을 수 없어요.
- 측정값을 끌어다 놓으면 Tableau Desktop은 다음 오류를 보고해요:
Unable to complete action Error Code: B9F09DDB SQL compilation error: error line 3 at position 8 Invalid metric expression 'COUNT(1)'.
- 측정값을 끌어다 놓으면 Tableau Desktop은 다음 오류를 보고해요:
- 비숫자 메트릭을 직접 사용할 수 없어요.
SYSTEM$EXPORT_TDS_FROM_SEMANTIC_VIEW는 비숫자 메트릭을 Tableau의 차원으로 변환해요. 이 차원 중 하나를 사용하려고 하면 Tableau Desktop은 다음 오류를 보고해요:Unable to complete action Error Code: B9F09DDB SQL compilation error: Requested semantic expression 'CUSTOMER.MIN_NAME' in DIMENSIONS clause must be one of the following types: (DIMENSION, FACT).- 이 문제를 해결하려면 차원을 측정값으로 변환해요:
- 차원을 마우스 오른쪽 버튼으로 클릭하고 Convert to Measure를 선택해요.
- 이러면 기본 집계 Count (Distinct)를 사용해 차원이 측정값으로 변환돼요.
- 다른 집계를 사용하려면 변환된 측정값을 마우스 오른쪽 버튼으로 클릭하고 Default Properties » Aggregations를 선택한 다음 사용하려는 집계를 선택해요.
- 차원을 마우스 오른쪽 버튼으로 클릭하고 Convert to Measure를 선택해요.
시맨틱 뷰 이름 바꾸기
시맨틱 뷰 이름을 바꾸려면 ALTER SEMANTIC VIEW ... RENAME TO ...을 실행해요. 예를 들어:
ALTER SEMANTIC VIEW sv RENAME TO sv_new_name;
시맨틱 뷰 제거하기
시맨틱 뷰를 제거하려면 DROP SEMANTIC VIEW 명령어를 실행해요. 예를 들어:
DROP SEMANTIC VIEW tpch_rev_analysis;
시맨틱 뷰에 권한 부여하기
시맨틱 뷰 권한은 시맨틱 뷰에 부여할 수 있는 권한을 나열해요.
뷰 작업에 필요한 시맨틱 뷰 권한은 다음과 같아요:
- 그 뷰에 대해 DESCRIBE SEMANTIC VIEW 명령어를 실행하려면 뷰에 대한 어떤 권한(예: MONITOR, REFERENCES 또는 SELECT)이 필요해요.
- SHOW SEMANTIC VIEWS 명령어의 출력에 그 뷰를 표시하려면 뷰에 대한 어떤 권한이 필요해요.
- 시맨틱 뷰를 쿼리하려면 SELECT가 필요해요.
참고: 시맨틱 뷰를 쿼리하려면 시맨틱 뷰에서 사용하는 테이블에 대한 SELECT 권한이 필요하지 않아요. 시맨틱 뷰 자체에 대한 SELECT 권한만 필요해요.
이 동작은 표준 뷰를 쿼리하는 데 필요한 권한과 일치해요.
Cortex Agents에서 소유하지 않은 시맨틱 뷰를 사용하려면 그 뷰에 대한 SELECT 권한이 있는 역할을 사용해야 해요.
시맨틱 뷰에 SELECT 권한을 부여하려면 GRANT <privileges> ... TO ROLE 명령어를 사용해요. 예를 들어 my_semantic_view라는 시맨틱 뷰에 my_analyst_role 역할에 SELECT 권한을 부여하려면 다음 문을 실행할 수 있어요:
GRANT SELECT ON SEMANTIC VIEW my_semantic_view TO ROLE my_analyst_role;
Cortex Agents 사용자와 공유하려는 시맨틱 뷰가 포함된 스키마가 있다면, 미래 권한(future grants)을 사용해 그 스키마에서 만들 아무 시맨틱 뷰에도 권한을 부여할 수 있어요. 예를 들어:
GRANT SELECT ON FUTURE SEMANTIC VIEWS IN SCHEMA my_schema TO ROLE my_analyst_role;