多くのチームはCSVエクスポートから始め、必要以上に長くその方法を使い続けます。そして取締役会向けの資料に載っている売上数値がデータベースの実績と食い違う事態が起きて、初めて「ちゃんとした仕組みが必要だ」という話になります。
手動CSVエクスポートが破綻する理由
エクスポートして貼り付けるワークフローは、単に手間がかかるだけではありません。データの信頼性を損なうリスクがあります。特定時点のデータを手動でコピーし、その静的なスナップショットを「最新情報」として扱われる場所に置く——これが問題の本質です。
Fivetranが2023年に実施したグローバル調査によると、データアナリストの67%が、自動化できる手動データ移行作業に週4時間以上を費やしているとのことです。スプレッドシートとデータベース間の同期は、その筆頭に挙がるタスクのひとつです。
週次・月次レポートを回している財務・経営企画チームにとって、古いPostgresのエクスポートデータは、実際の取引データより数日〜数週間遅れた損益数値を意味します。問題は担当者のスキル不足ではありません。「CSVをダウンロードしてSheetsに貼る」という手軽な方法が、一度きりの作業以外にはスケールしないことが本質的な課題です。
4つの方法を比較する
| 方法 | 初期設定時間 | データ更新 | SQLの柔軟性 | コスト |
|---|---|---|---|---|
| CSVエクスポート/インポート | 5分 | 手動のみ | 高い | 無料 |
| Apps Script+JDBC | 2〜4時間 | 自動化可能 | 高い | 無料 |
| ETLツール(Fivetran、Airbyte等) | 30〜60分 | 自動化可能 | 低い | 月額7,000〜70,000円以上 |
| DuckDB(専用アドオン経由) | 10分 | オンデマンド | 高い | 利用料に含む |
どれを選ぶかは、コードを書けるエンジニアリングリソースがあるか、インフラコストを負担できるか、あるいは自然な言葉で操作したいかによって変わります。
PostgreSQLをGoogle SheetsにつなぐApps Script+JDBC
Google Apps ScriptはPostgreSQLへのJDBC接続を直接サポートしています。接続を開き、クエリを実行し、結果を指定したセル範囲に書き込む関数を記述し、自動トリガーで更新スケジュールを設定します。
この方法はエンジニアリングリソースがある場合に限って有効です。JavaScriptを書ける人材が社内にいて、かつサーバー設定も担当できるなら、無料で動く仕組みが作れます。財務・経営企画の担当者が自分で設定しようとすると、後述の制約で詰まることが多いため、IT部門への依頼を前提に検討してください。
最低限の実装例は以下のとおりです。
function syncFromPostgres() {
const conn = Jdbc.getConnection(
'jdbc:postgresql://your-host:5432/your_db',
'username',
'password'
);
const stmt = conn.prepareStatement(
'SELECT date, revenue, cogs, gross_margin FROM financials.p_and_l WHERE date >= CURRENT_DATE - 90'
);
const results = stmt.executeQuery();
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('P&L');
let row = 2;
while (results.next()) {
sheet.getRange(row, 1, 1, 4).setValues([[
results.getString(1),
results.getFloat(2),
results.getFloat(3),
results.getFloat(4)
]]);
row++;
}
results.close();
conn.close();
}
これは動作しますが、実運用上の制約があります。GoogleのJDBC接続では、PostgreSQLインスタンスをパブリックアクセス可能にするか、GoogleのIPレンジをホワイトリストに登録する必要があります。これはセキュリティ上の妥協点であり、多くのチームが受け入れられない条件です。2026年3月時点でGoogleはApps ScriptのIPアドレス一覧を安定的に公開していないため、ファイアウォール設定が事実上の手探り作業になります。
また、Apps Scriptの実行タイムアウトは、通常アカウントで6分、Google Workspaceで30分です。クエリ結果が数千行を超えると、この上限に引っかかります。
ETLコネクター:一部のチームには最適、他には過剰
Fivetran、Airbyte、Stitchといったツールは、PostgreSQLのテーブルをGoogle Sheets(より一般的にはBigQuery経由でSheets)に同期します。設定自体はシンプルで、ソースを設定し、同期先を認証し、スケジュールを組めば完了です。
問題はコストと抽象化のレベルです。Fivetranの基本プランは月額約1万4,000円からで、月間アクティブ行数によって課金されます。Airbyteのクラウド版は同期レコード100万件あたり約430円程度から。3テーブルを毎日同期するチームなら費用対効果は合うかもしれませんが、本番Postgresインスタンスに対してアドホッククエリを実行したいアナリスト個人には過剰です。
さらに重要な課題があります。ETLコネクターはテーブル全体をレプリケーションします。ソースに対してSQLを書くのではなく、同期するテーブルを設定し、その後は同期先でクエリを実行する形です。特定のフィルター条件で4テーブルをJOINした結果が欲しい場合、そのロジックはどこか別の場所に置く必要があります。
DuckDB:多くのアナリストがまだ試していない選択肢
DuckDBにはpostgres拡張機能が標準で含まれており、PostgreSQLデータベースをクエリ可能なソースとしてアタッチできます。このアーキテクチャを使うと、Postgresインスタンスに対して直接SQLを書き、結果をスプレッドシートに出力できます。
内部的な接続設定は以下のようになります。
ATTACH 'dbname=analytics user=readonly password=... host=db.internal port=5432'
AS pg (TYPE postgres);
SELECT
date_trunc('month', t.created_at) AS month,
p.name AS product,
SUM(t.amount) AS revenue,
COUNT(*) AS transaction_count
FROM pg.transactions t
JOIN pg.products p ON t.product_id = p.id
WHERE t.created_at >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY 1, 2
ORDER BY 1 DESC, 3 DESC;
結果はシートに直接反映されます。中間的なデータウェアハウスにデータをコピーするのではなく、DuckDBのメモリを通じてPostgresにクエリを実行し、その出力をセル範囲に書き込む形です。
この方式はModelMonkeyのDuckDB連携ドキュメントに詳しく記載されており、ETLパターンとは本質的に異なります。SQLは毎回、ライブデータに対して新鮮に実行されます。
データが着地した後:財務モデルとの統合
「データがシートに書き出される」と聞いて、財務担当者が最初に気になるのはそこから先のはずです。既存のINDEX/MATCHは壊れないのか。8タブある財務モデルの下流タブが参照している範囲は上書きされないか。月次の書式設定は毎回やり直しになるのか。
Apps ScriptとDuckDB経由のアプローチはいずれも、指定したセル範囲に値を書き込む形になります。つまり、その範囲の外——別タブから='受注データ'!B2で参照している集計セルや、データ範囲の右側に作った差異分析の列——には影響しません。ただし、書き込まれる範囲そのものは上書きされるため、その範囲内に手入力した数値やコメントは消えます。
実運用で問題になりやすいパターンを以下に挙げます。
行数が変動する場合: クエリ結果が月によって50行だったり120行だったりする場合、前回の実行で書き込まれた行数が今回のデータより多いと古いデータが残ります。これはApps Scriptでもアドオン経由のDuckDBでも同様です。対策としては、書き込み前に対象範囲をクリアする処理を入れるか、クエリ側で行数を固定します。
書式の保持: セルの書式(通貨表示、パーセント、条件付き書式)は、値の書き込みでは消えません。Apps ScriptのsetValues()も、DuckDB経由の書き込みも、セルの書式設定はそのまま保持されます。月次レポートのテンプレートを作り込んでおいて、データだけを差し替えるという使い方が成立します。
既存のINDEX/MATCHへの影響: データが同じ列構成で同じ位置に書き込まれる限り、別タブからの参照は正常に機能します。列の順序が変わったり、新しい列が挿入されたりするとズレが生じるため、クエリのSELECT句の順序を変えないことが重要です。
まとめると、「Postgresから引いてきたデータを既存の財務モデルの一部として使う」という使い方は十分に成立します。データが着地するシートをデータソース専用タブとして設計し、分析・集計ロジックは別タブに置く構造にしておくことで、予期しない上書きを防げます。
Postgres→Sheets連携で誰も教えてくれないこと
接続そのものは、実は簡単な部分です。難しいのは認証情報の管理です。
CSVエクスポート以外のすべての方法では、Postgresの認証情報をどこかに保管する必要があります。Apps Scriptのプロジェクトプロパティ、サードパーティコネクターの暗号化ストレージ、あるいはシークレット管理システム——いずれもリスクの性質が異なります。
Apps Scriptの場合、認証情報はスクリプトプロパティに保存されます。Google Apps Scriptのドキュメントには、「スクリプトプロパティはスクリプトの全ユーザーで共有される」と明記されています。つまり、スプレッドシートの編集権限を持つ全員が、そこに保存したデータベースのパスワードを読み取れる状態になります。これは想定より多くの人数が対象になりがちです。
本ツールのPostgres連携では、Google Cloud KMSによるエンベロープ暗号化を採用しており、認証情報はユーザーごとの鍵でラップされます。平文のパスワードがディスクに保存されることはありません。本番データや機密性の高い情報を扱うPostgresインスタンスであれば、この違いは見逃せません。
Postgres接続をセットアップする手順
- Google SheetsでサイドバーのAIアドオンを開く
- データソースに移動し、接続を追加を選択
- プロバイダーの種類としてPostgreSQLを選択
- ホスト、ポート、データベース名、スキーマを入力
- 認証情報を入力(暗号化されて保存され、平文では保持されません)
- 接続テストをクリックして疎通を確認
- 接続完了後、そのままクエリを実行:「過去90日間の受注データを商品カテゴリ別に集計して」
本ツールは自然言語の指示をSQLに変換し、DuckDB経由でPostgresインスタンスに対して実行、結果をアクティブなシートに書き出します。次回以降は認証情報を再入力することなく、いつでも同じクエリを再実行できます。
DuckDBをSheets分析にすでに活用しているチームであれば、PostgreSQLコネクターも同じワークフローに自然に組み込めます。同じクエリツール、同じ出力フォーマット——データソースが変わるだけです。
よくある質問
PostgreSQLのデータをGoogle Sheetsに自動で同期するには何が必要ですか?
自動同期を実現するには、CSVの手動エクスポート以外の方法が必要です。Apps Script+JDBCであれば無料で時間ベースのトリガー設定が可能ですが、エンジニアリングリソースとセキュリティ上の妥協が伴います。ETLツールは設定が容易ですが月額コストが発生します。DuckDB経由のアドオンはオンデマンドでのクエリ実行が得意で、財務・経営企画の月次作業に向いています。
Apps ScriptでPostgresに接続できない場合、何が原因ですか?
最も多い原因はファイアウォールの設定です。GoogleのJDBC接続はPostgreSQLインスタンスへのパブリックアクセスを必要とするか、GoogleのIPレンジをホワイトリストに追加する必要があります。2026年3月時点でGoogleはIPレンジを安定的に公開していないため、IT部門との連携が不可欠です。
ETLツールとDuckDB経由のライブクエリ、どちらを選ぶべきですか?
複数のテーブルを定期的に丸ごと同期してデータウェアハウスに蓄積したい場合はETLツールが向いています。Postgresの最新データに対してその都度フレキシブルなSQLを実行し、結果をシートに直接出力したい場合はDuckDB経由のアプローチが適しています。予実管理や月次損益の集計など、財務・経営企画の定型作業には後者が合うケースが多いです。
PostgreSQLからデータを書き込んでも、既存のINDEX/MATCHは壊れませんか?
データが同じ列構成・同じセル範囲に書き込まれる限り、別タブからの参照は機能し続けます。書式設定(通貨表示・条件付き書式)も保持されます。ただし書き込み範囲内のデータは上書きされるため、データソースタブと分析・集計タブを分けて設計しておくことを推奨します。
Apps Scriptのタイムアウト制限は大量データで実際に問題になりますか?
なります。通常のGoogleアカウントでは実行時間が6分、Google Workspaceでも30分が上限です。クエリ結果が数千行を超えるケースではこの制限に引っかかります。取引明細や顧客データのような行数の多いテーブルを扱う場合は、ETLツールかDuckDB経由の方法が現実的です。