Clean Room 테이블에서 자유 형식 SQL 쿼리 실행하기

You can enable consumers to run free-form SQL queries on selected datasets in your clean room using either the clean room API or UI.

Free-form queries using the clean rooms API

You can configure a clean room to allow collaborators to query specific linked datasets from outside the clean room. Collaborators can run free-form queries on these datasets in any environment where they can access the clean room, including Snowsight or Snowflake CLI. Free-form datasets behave as standard, read-only views that can be queried using SQL, Python, or other supported Snowflake languages.

참고

When you grant a consumer permission to run free-form SQL queries in a clean room, that consumer can query the data from that clean room against any other data that they can access from their account.

정책 및 차등 개인정보 보호 지원

자유 형식 쿼리를 위해 Clean Room 데이터를 노출하는 경우, 모든 Snowflake 정책이 준수됩니다. Clean Room 정책(조인 정책, 열 정책)은 자유 형식 쿼리에서 적용되지 않습니다.

Clean room differential privacy is not enforced on data exposed to free-form queries. This includes both Snowflake differential privacy and clean room differential privacy.

자유 형식 쿼리 활성화하기

중요

If a clean room was created before June, 2025 the provider must patch their clean room by running the following code to enable free-form queries in that clean room:

USE ROLE SAMOOHA_APP_ROLE;
CALL samooha_by_snowflake_local_db.provider.patch_cleanroom($cleanroom_name,TRUE);
Copy

Provider steps

공급자는 다음 단계를 수행하여 Clean Room 공동 작업자가 자유 형식 쿼리를 사용하여 Clean Room의 데이터 세트를 사용할 수 있습니다.

  1. 표준 방식으로 Clean Room을 만듭니다.

  2. Register and link the datasets into the clean room in the standard way using the API. Note that currently your data must be registered using the API; you cannot register views in the clean room UI and use them for free-form queries. You should apply any Snowflake aggregation, join, or other policies before sharing your data outside the clean room.

  3. Call provider.enable_workflows_for_consumers to allow specific users free-form access to the tables that you will specify in the next step. You must name this work flow freeform_sql.

  4. Call provider.enable_datasets_for_workflow to specify which datasets in the clean room can be queried.

  5. provider.add_consumers 를 호출하여 표준 방식으로 공동 작업자를 추가합니다.

  6. Clean Room을 게시합니다.

  7. If you want to revoke permission to query these tables, you can do this at the user level by calling provider.disable_consumer_run_analysis or provider.remove_consumers, at the dataset level by calling library.unregister_objects or library.unregister_db, or by deleting the clean room.

If a clean room already exists and data is registered, you can simply call provider.enable_workflows_for_consumers and provider.enable_datasets_for_workflow to expose the specified datasets to the specified users.

The following code creates three sample tables and applies Snowflake policies to them, creates a new clean room, links in the tables, and grants free-form query access to those tables for clean room collaborators via the clean room. The highlighted code shows where you enable free-form queries in the clean room.

----------------- Create sample data -----------------
USE ROLE MYROLE;
CREATE DATABASE freeform_db;

-- Create a table with an aggregation constraint.
CREATE OR REPLACE TABLE freeform_db.public.agg_constrained_table
  AS SELECT * FROM SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS;

CREATE AGGREGATION POLICY freeform_db.public.agg_policy AS ()
  RETURNS AGGREGATION_CONSTRAINT ->
  AGGREGATION_CONSTRAINT(MIN_GROUP_SIZE => 5);

ALTER TABLE freeform_db.public.agg_constrained_table
  SET AGGREGATION POLICY freeform_db.public.agg_policy;

-- Create a table with a projection constraint.
CREATE OR REPLACE TABLE freeform_db.public.proj_constrained_table
  AS SELECT * FROM SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS;

CREATE OR REPLACE PROJECTION POLICY freeform_db.public.proj_policy AS ()
  RETURNS PROJECTION_CONSTRAINT ->
  PROJECTION_CONSTRAINT(ALLOW => false);

ALTER TABLE freeform_db.public.proj_constrained_table MODIFY COLUMN hashed_email
  SET PROJECTION POLICY freeform_db.public.proj_policy;

-- Create a table with a masking policy.
CREATE OR REPLACE TABLE freeform_db.public.masked_table
  AS SELECT * FROM SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS;

CREATE OR REPLACE MASKING POLICY freeform_db.public.masking_policy
  AS (val string) RETURNS STRING ->
  CASE
    WHEN current_account() IN ('DCR_PROVIDER_PP6') THEN VAL
    ELSE '*********'
  END;

ALTER TABLE freeform_db.public.masked_table MODIFY COLUMN hashed_email
  SET MASKING POLICY freeform_db.public.masking_policy;

----------------- Create and publish a clean room that supports -----------------
----------------- free-form queries against this data.          -----------------

-- Create the clean room. Nothing new here.
USE ROLE SAMOOHA_APP_ROLE;
SET cleanroom_name = 'freeform queries';
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.cleanroom_init($cleanroom_name, 'INTERNAL');

-- Link in the policy-protected tables from above. Nothing new here.
USE ROLE MYROLE;
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.register_db('freeform_db');
USE ROLE SAMOOHA_APP_ROLE;
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.link_datasets($cleanroom_name,
  ['freeform_db.public.agg_constrained_table',
  'freeform_db.public.proj_constrained_table',
  'freeform_db.public.masked_table']);

-- Grant the following consumer access to the tables specified next.
-- The flow name must be 'freeform_sql'
SET flow_name = 'freeform_sql';
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.enable_workflows_for_consumers($cleanroom_name,
  [$flow_name],
  ['<CONSUMER_LOCATOR>']);

-- Grant the consumer specified above access to the specified tables.
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.enable_datasets_for_workflow($cleanroom_name,
  $flow_name,
  ['freeform_db.public.agg_constrained_table',
   'freeform_db.public.proj_constrained_table',
   'freeform_db.public.masked_table']);

-- Add collaborators and publish, in the standard way.
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.add_consumers(
  $cleanroom_name, '<CONSUMER_LOCATOR>', '<ORG_NAME>.<CONSUMER_LOCATOR>');
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.set_default_release_directive(
  $cleanroom_name, 'V1_0', '0');
CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.provider.create_or_update_cleanroom_listing(
  $cleanroom_name);
Copy

Consumer steps

After the provider has published a clean room with free-form SQL work flows, consumers with access to that clean room can run queries against the exposed views by following these steps:

  1. Install the clean room in the standard way. No need to link in consumer data, as the consumer will access their data in their local environment, not in the clean room.

  2. consumer.get_provider_freeform_sql_views 를 호출하여 현재 계정 및 역할에 사용할 수 있는 자유 형식의 SQL 뷰를 목록으로 확인합니다.

  3. Run standard SQL queries against the data.

-- Install the clean room.
USE ROLE SAMOOHA_APP_ROLE;
SET cleanroom_name = 'freeform queries';

CALL samooha_by_snowflake_local_db.consumer.install_cleanroom($cleanroom_name, '<PROVIDER_LOCATOR>');

-- List free form views available in the clean room.
CALL samooha_by_snowflake_local_db.consumer.GET_PROVIDER_FREEFORM_SQL_VIEWS($cleanroom_name);

-- Run queries on the views
SELECT * FROM <PROJECTION_POLICY_VIEW_NAME>;
SELECT * FROM <MASKING_POLICY_VIEW_NAME>;
SELECT COUNT(hashed_email), age_band
  FROM <AGGREGATION_POLICY_VIEW_NAME> group by age_band;
Copy

Clean Rooms UI 의 자유 형식 쿼리

Clean Room에 SQL Query 템플릿을 사용하면 컨슈머가 자유 형식의 SQL 을 작성하여 Clean Room의 데이터를 쿼리할 수 있습니다. SQL Query 템플릿을 사용할 때 소비자 쿼리가 특정 요건을 충족해야 결과를 성공적으로 반환할 수 있습니다. 이러한 요구 사항은 데이터 공급자가 데이터 개인정보 보호 정책을 통해 테이블을 보호하는 방법에 따라 결정됩니다.

UI 에서 Clean Room을 만들거나 업데이트할 때 SQL Query 템플릿을 Clean Room에 추가하고 아래에 설명된 대로 구성합니다.

공급자: Clean Room 생성 및 정책 설정

  1. Clean Room을 만들거나 기존 Clean Room을 편집하고 테이블 또는 뷰를 지정할 수 있습니다.

  2. SQL Query 템플릿을 사용할 때는 Clean Room 생성 프로세스 중에 지정된 조인 정책이 무시되지만 다른 템플릿에서는 적용됩니다.

  3. Configure Analysis & Query 에서 Horizontal » SQL Query 를 선택합니다.

  4. SQL Query 설정 섹션에서 다음 속성을 설정합니다.

    1. Under Tables, select tables that should be available to clean room collaborators in free-form queries. By default, aggregation policies do not need to be applied. To control which columns can be projected, and which must be aggregated, you must set column policies in the next section.

      중요

      클린룸 UI의 자유 형식 쿼리에서는 이름이 “LIST”(대문자 또는 소문자)로 끝나는 테이블을 사용할 수 없습니다.

    2. Column Policies 섹션에서 다음 값을 설정하여 쿼리에서 열을 사용할 수 있는지 여부와 방법을 제어합니다.

      1. Aggregation policy columns: 쿼리 결과에 표시하기 위해 집계해야 하는 열을 지정합니다. 열에 집계 정책을 적용하고 쿼리에서 하나의 열이 사용되는 경우 결과를 집계해야 합니다. 여기에 나열된 모든 열은 Privacy settings 섹션에 추가됩니다.

      2. Projection policy columns: 프로젝션 정책이 있는 열은 프로젝션할 수 없습니다 (즉, SELECT 문에 포함됨). 그러나 컨슈머는 프로젝션 정책을 통해 열에 필터링하거나 조인할 수 있습니다.

      3. Fully permitted columns: 컨슈머는 SELECT, 필터링하거나 제한 없이 이러한 열에 조인할 수 있습니다(집계 또는 기타).

    3. Privacy settings 섹션에는 집계 정책이 적용된 모든 열이 나열됩니다. Threshold 값은 해당 값이 결과에 표시되려면 얼마나 많은 엔터티가 있어야 하는지를 나타냅니다. 예를 들어 FIRST_NAME 열에 임계값을 5로 설정하고 “Erasmus”라는 이름이 테이블에 4번만 나타나는 경우 “Erasmus”가 포함된 모든 행은 처리되기 전에 필터링됩니다(예: 해당 테이블의 COUNT(*)는 임계값 이하의 그룹 크기를 가진 4행이 생략됨).

컨슈머: 자유 형식 쿼리 실행하기

  1. Clean Rooms UI 에서 Clean Room에 참여하거나 편집합니다.

  2. Configure Analysis & Query 섹션에서 자유 형식 쿼리에 사용할 테이블을 선택합니다.

    중요

    클린룸 UI의 자유 형식 쿼리에서는 이름이 “LIST”(대문자 또는 소문자)로 끝나는 테이블을 사용할 수 없습니다.

  3. Finish 를 선택하여 변경 사항을 저장합니다.

  4. 쿼리를 실행하려면 SQL Query 템플릿이 있는 Clean Room에서 Run 을 선택하고 SQL Query 템플릿을 선택합니다.

조인 및 필터링 열 선택하기

정책이 있거나 완전히 허용된 모든 열에 조인하고 필터링할 수 있습니다. 열을 필터에 조인하거나 사용할 수 있는지 여부를 결정합니다.

  1. Query Configurations 섹션에서 Tables 타일을 찾습니다.

  2. 드롭다운 목록을 사용하여 테이블을 선택합니다. 목록에 있는 모든 열에 조인하고 필터링할 수 있습니다.

투영 열 선택하기

SQL Query 템플릿을 사용하여 실행되는 쿼리에는 프로젝션할 수 있는 열에 제한이 있습니다(SELECT 문에 사용됨).

쿼리가 열을 프로젝션할 수 있는지 확인하려면:

  1. Query Configurations 섹션에서 Tables 타일을 찾습니다.

  2. 드롭다운 목록을 사용하여 테이블을 선택합니다.

  3. 프로젝션 정책 레이블이 있는 열을 찾으면 프로젝션할 수 없음을 의미합니다. 프로젝션 정책 레이블이 있는 열을 제외한 모든 열을 프로젝션할 수 있습니다.

집계 요구 사항

공급자가 열에 집계 정책을 지정한 경우 SQL 쿼리 템플릿을 사용하여 실행되는 모든 쿼리는 집계된 결과를 반환해야 합니다.

쿼리 결과를 집계해야 하는지 여부를 결정합니다.

  1. Query Configurations 섹션에서 Tables 타일을 찾습니다.

  2. 드롭다운 목록을 사용하여 테이블을 선택합니다.

  3. 집계 정책 레이블이 있는 열을 찾습니다. 집계 정책 레이블이 하나 이상 있는 경우 쿼리에서 집계를 사용해야 합니다.

집계 정책으로 보호되는 데이터에 대한 성공적인 쿼리를 작성하는 방법에 대한 지침은 다음을 참조하십시오.

그래프 작성 요구 사항

Snowflake가 그래프를 생성하려면 다음이 필요합니다.

  • 결과 테이블에는 최소한 1개의 측정값(숫자) 열과 1개의 차원(카테고리) 열이 포함되어야 합니다.

  • 측정값 열 이름에는 다음 접두사 또는 접미사가 있어야 합니다(대/소문자 구분 안 함).

    • 열 이름 접두사:

      • COUNT

      • SUM

      • AVG

      • MIN

      • MAX

      • OUTPUT

      • OVERLAP

    • 열 이름 접미사:

      • _OVERLAP

Snowflake는 결과 테이블에서 첫 번째 적격 측정값 열과 첫 번째 차원 열을 사용하여 차트를 생성합니다.

제한 사항

  • ORDER BY 절은 분석 결과가 표시되는 방식에 영향을 미치지 않습니다.

샘플 쿼리

이 섹션을 사용하여 SQL Query 템플릿으로 분석을 실행할 때 쿼리에 포함할 수 있는 항목과 포함할 수 없는 항목을 더 잘 이해할 수 있습니다.

집계 함수가 없는 쿼리

어떤 경우에는 집계 함수를 사용하지 않고도 값을 반환할 수 있습니다.

허용됨

허용되지 않음

SELECT gender, regions
  FROM TABLE sample_db.demo.customer
  GROUP BY gender, region;
Copy
SELECT gender, regions
  FROM TABLE sample_db.demo.customer;
Copy
일반 테이블 식(CTEs)

허용됨

허용되지 않음

WITH audience AS
  (SELECT COUNT(DISTINCT t1.hashed_email),
    t1.status
    FROM provider_db.overlap.customers t1
    JOIN consumer_db.overlap.customers t2
      ON t1.hashed_email = t2.hashed_email
    GROUP BY t1.status);

SELECT * FROM audience;
Copy
WITH audience AS
  (SELECT t1.hashed_email,
    t1.status
    FROM provider_db.overlap.customers quoted t1
    JOIN consumer_db.overlap.customers t2
      ON t1.hashed_email = t2.hashed_email
    GROUP BY t1.status)

SELECT * FROM audience
Copy
CREATE, ALTER, TRUNCATE

쿼리에서는 CREATE, ALTER 또는 TRUNCATE를 사용할 수 없습니다.

조인을 사용한 쿼리

허용됨

SELECT p.education_level,
  c.status,
  AVG(p.days_active),
  COUNT(DISTINCT p.age_band)
  FROM  samooha_sample_database.demo.customers c
  INNER JOIN
  samooha_sample_database.demo.customers p
    ON  c.hashed_email = p.hashed_email
  GROUP BY ALL;
Copy
DATE_TRUNC

허용됨

SELECT COUNT(*),
  DATE_TRUNC('week', date_joined) AS week
  FROM consumer_sample_database.audience_overlap.customers
  GROUP BY week;
Copy
따옴표가 있는 식별자

허용됨

SELECT COUNT(DISTINCT t1."hashed_email")
  FROM provider_sample_database.audience_overlap."customers quoted" t1
  INNER JOIN
  consumer_sample_database.audience_overlap.customers t2
    ON t1."hashed_email" = t2.hashed_email;
Copy