Dataform コアのスクリプト例

このドキュメントでは、Dataform で SQL ワークフローを作成する際に使用できる Dataform のコアスクリプトと JavaScript スクリプトの例を示します。

テーブルの作成

Dataform コアを使用してビューを作成する

次のコードサンプルは、definitions/new_view.sqlx ファイル内の new_view というビューの定義を示しています。

config { type: "view" }

SELECT * FROM source_data

Dataform コアを使用して実体化されたビューを作成する

次のコードサンプルは、definitions/new_materialized_view.sqlx ファイル内の new_materialized_view というマテリアライズド ビューの定義を示しています。

config {
  type: "view",
  materialized: true
}

SELECT * FROM source_data

Dataform コアを使用してテーブルを作成する

次のコードサンプルは、definitions/new_table.sqlx ファイル内の new_table というテーブルの定義を示しています。

config { type: "table" }

SELECT * FROM source_data

Dataform コアを使用して増分テーブルを作成する

次のコードサンプルは、productiondb.logs テーブルの行をインクリメントに処理する増分テーブルを示しています。

config { type: "incremental" }

SELECT timestamp, message FROM ${ref("productiondb", "logs")}

${when(incremental(), `WHERE timestamp > (SELECT MAX(timestamp) FROM ${self()})`) }

ref 関数を使用して Dataform コアでテーブルを参照する

次のコードサンプルは、definitions/new_table_with_ref.sqlx テーブル定義ファイル内の source_data テーブルを参照するために使用される ref 関数を示しています。

config { type: "table" }

SELECT * FROM ${ref("source_data")}

Dataform コアを使用してテーブル、ビュー、宣言にドキュメントを追加する

次のコードサンプルは、definitions/documented_table.sqlx テーブル定義ファイル内のテーブルと列の説明を示しています。

config { type: "table",
         description: "This table is an example",
         columns:{
             user_name: "Name of the user",
             user_id: "ID of the user"
      }
  }

SELECT user_name, user_id FROM ${ref("source_data")}

増分テーブルの構成

Dataform コアを使用して、ソースデータの新しい日付の新しいテーブル行を追加する

次のコードサンプルは、definitions/incremental_table.sqlx ファイルの増分テーブルの構成を示しています。この構成では、新しい日付ごとに新しい行が incremental_table に追加されます。

config { type: "incremental" }

SELECT date(timestamp) AS date, action
FROM weblogs.user_actions

${ when(incremental(), `WHERE timestamp > (select max(date) FROM ${self()})`)

Dataform コアを使用してテーブルのスナップショットを定期的に取得する

次のコードサンプルは、definitions/snapshots_table.sqlx ファイル内の増分テーブルの構成を示しています。この構成では、Dataform は指定した日付の productiondb.customers のスナップショットを使用して snapshots_table を作成します。

config { type: "incremental" }

SELECT current_date() AS snapshot_date, customer_id, name, account_settings FROM productiondb.customers

${ when(incremental(), `WHERE snapshot_date > (SELECT max(snapshot_date) FROM ${self()})`) }

Dataform コアを使用して増分更新される 30 日間のローリング テーブルを作成する

次のコードサンプルは、definitions/incremental_example.sqlx ファイル内の増分テーブルの構成を示しています。この構成では、Dataform は一時的な incremental_example を作成し、増分更新し、作成から 30 日後にテーブルを削除します。

config {type: "incremental"}

post_operations {
  delete FROM ${self()} WHERE date < (date_add(Day, -30, CURRENT_DATE))
}

SELECT
 date(timestamp) AS date,
 order_id,
FROM source_table
  ${ when(incremental(), `WHERE timestamp > (SELECT max(date) FROM ${self()})`) }

カスタム SQL オペレーションを作成する

Dataform コアを使用して SQLX ファイルで複数の SQL オペレーションを実行する

次のコードサンプルは、definitions/operations.sqlx で定義された複数の SQL オペレーションの分離に使用される ; を示しています。

config { type: "operations" }

DELETE FROM datatable where country = 'GB';
DELETE FROM datatable where country = 'FR';

Dataform コアでテーブルを作成する前にカスタム SQL を実行する

次のコードサンプルは、definitions/table_with_preops.sqlx テーブル定義ファイルの pre_operations ブロックで定義されているカスタム SQL オペレーションを示しています。

config {type: "table"}

SELECT * FROM ...

pre_operations {
  INSERT INTO table ...
}

Dataform コアでテーブルを作成した後にカスタム SQL を実行する

次のコードサンプルは、definitions/table_with_postops.sqlx テーブル定義ファイルの post_operations ブロックで定義されているカスタム SQL オペレーションを示しています。

config {type: "table"}

SELECT * FROM ...

post_operations {
  GRANT `roles/bigquery.dataViewer`
  ON
  TABLE ${self()}
  TO "group:allusers@example.com", "user:otheruser@example.com"
}

テーブルの検証

Dataform コアを使用してテーブル、ビュー、宣言にアサーションを追加する

次のコードサンプルは、definitions/tested_table.sqlx テーブル定義ファイルに追加された uniqueKeynonNullrowConditions アサーションを示しています。

config {
  type: "table",
  assertions: {
    uniqueKey: ["user_id"],
    nonNull: ["user_id", "customer_id"],
    rowConditions: [
      'signup_date is null or signup_date > "2022-01-01"',
      'email like "%@%.%"'
    ]
  }
}
SELECT ...

Dataform コアでカスタム アサーションを追加する

次のコードサンプルは、source_data の列 abcnull かどうかを検証するテーブル定義ファイルのカスタム アサーションを示しています。

config { type: "assertion" }

SELECT
  *
FROM
  ${ref("source_data")}
WHERE
  a is null
  or b is null
  or c is null

JavaScript での開発

JavaScript でインライン変数と関数を使用する

次のコードサンプルは、js ブロックで定義され、SQLX ファイルでインラインで使用される foo 変数を示しています。

js {
 const foo = 1;
 function bar(number){
     return number+1;
 }
}

SELECT
 ${foo} AS one,
 ${bar(foo)} AS two

JavaScript を使用して国ごとに 1 つのテーブルを生成する

次のコードサンプルは、forEach 関数を使用して、definitions/one_table_per_country.js ファイル内の countries で定義されている国ごとに 1 つのテーブルを生成する方法を示しています。

const countries = ["GB", "US", "FR", "TH", "NG"];

countries.forEach(country => {
  publish("reporting_" + country)
    .dependencies(["source_table"])
    .query(
      ctx => `
      SELECT '${country}' AS country
      `
    );
});

JavaScript で 1 つのファイル内に複数のソースを宣言する

次のコードサンプルは、definitions/external_dependencies.js ファイル内での複数のデータソースの宣言を示しています。

declare({
  schema: "stripe",
  name: "charges"
});

declare({
  schema: "shopify",
  name: "orders"
});

declare({
  schema: "salesforce",
  name: "accounts"
});

forEach を使用して 1 つのファイル内に複数のソースを宣言する

次のコードサンプルは、definitions/external_dependencies.js ファイルで forEach 関数を使用して複数のデータソースを宣言する方法を示しています。

["charges", "subscriptions", "line_items", "invoices"]
  .forEach(source => declare({
      schema: "stripe",
      name: source
    })
  );

JavaScript を使用して PII を含むすべてのテーブルの機密情報を削除する

次のコードサンプルは、個人情報(PII)を含むすべてのテーブルから選択された情報を削除する definitions/delete_pii.js ファイルの関数を示しています。

const pii_tables = ["users", "customers", "leads"];
pii_tables.forEach(table =>
  operate(`gdpr_cleanup: ${table}`,
    ctx => `
      DELETE FROM raw_data.${table}
      WHERE user_id in (SELECT * FROM users_who_requested_deletion)`)
      .tags(["gdpr_deletion"]))
);

JavaScript で preOpspostOps を追加する

次のコードサンプルは、definitions/pre_and_post_ops_example.js テーブルで preOpspostOps を使用してクエリを作成するために使用される publish 関数を示しています。

publish("example")
  .preOps(ctx => `GRANT \`roles/bigquery.dataViewer\` ON TABLE ${ctx.ref("other_table")} TO "group:automation@example.com"`)
  .query(ctx => `SELECT * FROM ${ctx.ref("other_table")}`)
  .postOps(ctx => `REVOKE \`roles/bigquery.dataViewer\` ON TABLE ${ctx.ref("other_table")} TO "group:automation@example.com"`)

JavaScript を使用した増分テーブルの作成

次のコードサンプルは、definitions/incremental_example.js ファイルに増分テーブルを作成するために使用される publish 関数を示しています。

publish("incremental_example", {
  type: "incremental"
}).query(ctx => `
  SELECT * FROM ${ctx.ref("other_table")}
  ${ctx.when(ctx.incremental(),`WHERE timestamp > (SELECT MAX(date) FROM ${ctx.self()}`)}
`)

JavaScript を使用した日別テーブルのバックフィル

次のコードサンプルは、definitions/backfill_daily_data.js ファイルで毎日更新されるテーブルのバックフィルを示しています。

var getDateArray = function(start, end) {
  var startDate = new Date(start); //YYYY-MM-DD
  var endDate = new Date(end); //YYYY-MM-DD

  var arr = new Array();
  var dt = new Date(startDate);
  while (dt <= endDate) {
    arr.push(new Date(dt).toISOString().split("T")[0]);
    dt.setDate(dt.getDate() + 1);
  }
  return arr;
};

var dateArr = getDateArray("2020-03-01", "2020-04-01");

// step 1: create table
operate(`create table`, 'create table if not exists backfill_table (`fields`) `);
// step 2: insert into the table

dateArr.forEach((day, i) =>
  operate(`backfill ${day}`
   `insert into backfill_table select fields where day = '${day}'`)
);

インクルードを使用してコードを再利用する

JavaScript でグローバル変数を使用する

次のコードサンプルは、includes/constants.jsproject_id 定数と first_date 定数の定義を示しています。

const project_id = "project_id";
const first_date = "'1970-01-01'";
module.exports = {
  project_id,
  first_date
};

次のコードサンプルは、definitions/new_table.sqlx ファイルで参照される first_date 定数を示しています。

config {type: "table"}

SELECT * FROM source_table WHERE date > ${constants.first_date}

JavaScript を使用して国のマッピングを作成する

次のコードサンプルは、includes/mapping.js ファイルで定義された country_group カスタム関数を示しています。

function country_group(country){
  return `
  case
    when ${country} in ('US', 'CA') then 'NA'
    when ${country} in ('GB', 'FR', 'DE', 'IT', 'PL', 'SE') then 'EU'
    when ${country} in ('AU') then ${country}
    else 'Other'
  end`;
}

module.exports = {
   country_group
};

次のコードサンプルは、definitions/new_table.sqlx テーブル定義ファイルで country_group 関数を使用するテーブル定義を示しています。

config { type: "table"}

SELECT
  country AS country,
  ${mapping.country_group("country")} AS country_group,
  device_type AS device_type,
  sum(revenue) AS revenue,
  sum(pageviews) AS pageviews,
  sum(sessions) AS sessions

FROM ${ref("source_table")}

GROUP BY 1, 2, 3

次のコードサンプルは、SQL にコンパイルされた definitions/new_table.sqlx で定義されたクエリを示しています。

SELECT
  country AS country,
  case
    when country in ('US', 'CA') then 'NA'
    when country in ('GB', 'FR', 'DE', 'IT', 'PL', 'SE') then 'EU'
    when country in ('AU') then country
    else 'Other'
  end AS country_group,
  device_type AS device_type,
  sum(revenue) AS revenue,
  sum(pageviews) AS pageviews,
  sum(sessions) AS sessions

FROM "dataform"."source_table"

GROUP BY 1, 2, 3

カスタム JavaScript 関数を使用して SQL スクリプトを生成する

次のコードサンプルは、includes/script_builder.js で定義された render_script カスタム関数を示しています。

function render_script(table, dimensions, metrics) {
  return `
      SELECT
      ${dimensions.map(field => `${field} AS ${field}`).join(",")},
      ${metrics.map(field => `sum(${field}) AS ${field}`).join(",\n")}
      FROM ${table}
      GROUP BY ${dimensions.map((field, i) => `${i + 1}`).join(", ")}
    `;
}

module.exports = { render_script };

次のコードサンプルは、definitions/new_table.sqlx テーブル定義ファイルで render_script 関数を使用するテーブル定義を示しています。

config {
    type: "table",
    tags: ["advanced", "hourly"],
    disabled: true
}

${script_builder.render_script(ref("source_table"),
                               ["country", "device_type"],
                               ["revenue", "pageviews", "sessions"]
                               )}

次のコードサンプルは、SQL にコンパイルされた definitions/new_table.sqlx で定義されたクエリを示しています。

SELECT
  country AS country,
  device_type AS device_type,
  sum(revenue) AS revenue,
  sum(pageviews) AS pageviews,
  sum(sessions) AS sessions

FROM "dataform"."source_table"

GROUP BY 1, 2

アクションの構成

アクション構成を使用して SQL ファイルを読み込む

アクション構成を使用すると、純粋な SQL ファイルを簡単に読み込むことができます。アクション構成は、definitions フォルダの actions.yaml ファイルで定義できます。

使用可能なアクション タイプと有効なアクション構成オプションの詳細については、Dataform 構成リファレンスをご覧ください。

次のコードサンプルは、definitions/actions.yaml ファイル内の new_view というビューの定義を示しています。

actions:
  - view:
    filename: new_view.sql

上記のコードサンプルで参照されている definitions/new_view.sql SQL ファイルには、純粋な SQL が含まれています。

SELECT * FROM source_data