戻る

ブラウザー内 SQL ワークベンチ

データ変換

読み込み中

ツールを読み込んでいます

ツールのコードは開いたときにのみ読み込まれます。

このツールの処理はすべてブラウザー内で行われ、入力内容はサーバーへ送信されません。

このツールについて

CSV またはフラットな JSON 配列を名前付きの一時テーブルに読み込み、実際の SQLite SQL で絞り込み、結合、集計、並べ替えを行います。CSV の値は先頭ゼロを含めて文字列のまま保持し、JSON の基本値は対応する数値・文字列・NULL として扱います。sql.js エンジンはローカルの Web Worker で動作します。入力のアップロード、データ内 URL へのアクセス、入力履歴の保存は行いません。同じ配信元に同梱した SQLite WASM は 658,410 バイト(約 643 KiB)で、別途 Worker JavaScript も使います。取得は明示的な読み込み操作の後だけです。テーブルはこのページの一時セッションにだけ存在します。対象は CSV・JSON の読み込みと参照クエリであり、SQLite データベースファイルや Parquet ファイルを開く機能は含みません。

主な用途

  • 注文 CSV と顧客 JSON の参照表を LEFT JOIN で結合し、対応する顧客がない注文も確認する。
  • エクスポートを絞り込み、数値文字列を明示的に変換し、部署や地域ごとに集計して確認後にダウンロードする。
  • JSON の欠損値や文字列 ID を調べ、WITH 共通テーブル式で段階的なクエリを読みやすく記述する。

使い方

  1. 1.CSV または JSON を選び、一意のテーブル名を入力して、テキストを貼り付けるかローカルファイルを選び UTF-8・UTF-16LE・UTF-16BE を指定します。CSV はカンマ・セミコロン・タブ・縦線の区切りとヘッダーの有無を指定します。最大 8 件のソースを設定して一括読み込みし、各テーブルの列名と行数を確認します。無効なソースが一つでもあれば全体が失敗し、黙って除外することはありません。JSON はフラットなオブジェクト配列が必要で、入れ子のデータは先に別途変換してください。
  2. 2.表示されたテーブル名と列名を使い、必要なら WITH で始まる単一の SELECT を記述します。空白や記号を含む識別子は二重引用符で囲みます。CSV の数値は文字列なので、有効な数値であることを確認してから CAST を使います。順序を再現するには ORDER BY、結果を上限内に収めるには WHERE や LIMIT を加え、実行します。
  3. 3.CSV をダウンロードする前に、結果件数とページ分割されたプレビューを確認します。数式対策は既定で有効です。元の値で出力する場合は警告を読んで明示的に選択してください。出力対象は表示ページだけでなく、正常に得られた上限内の全結果です。キャンセルやリセットは Worker と全テーブルを破棄するため、続けるにはソースの再読み込みが必要です。

実行可能な CSV・JSON SQL の例

ID を保ったまま数値文字列を絞り込む

{
  "sources": [
    {
      "name": "stock",
      "format": "csv",
      "text": "id,units\n001,12\n002,3\n010,20",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT id, units FROM stock WHERE CAST(units AS INTEGER) >= 10 ORDER BY CAST(units AS INTEGER) DESC",
  "safe": true
}
{
  "columns": [
    "id",
    "units"
  ],
  "rows": [
    [
      "010",
      "20"
    ],
    [
      "001",
      "12"
    ]
  ]
}

CAST が変えるのは比較方法であり、選択する id と units の文字列ではありません。ID は 010 と 001 のままで、明示的な ORDER BY が 20 を 12 より先にします。

JSON の真偽値・数値・欠損キーを読み込む

{
  "sources": [
    {
      "name": "tickets",
      "format": "json",
      "text": "[{\"id\":\"T1\",\"open\":true,\"score\":4.5},{\"id\":\"T2\",\"open\":false,\"score\":null},{\"id\":\"T3\",\"open\":true}]",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT id, open, score FROM tickets ORDER BY id",
  "safe": true
}
{
  "columns": [
    "id",
    "open",
    "score"
  ],
  "rows": [
    [
      "T1",
      1,
      4.5
    ],
    [
      "T2",
      0,
      null
    ],
    [
      "T3",
      1,
      null
    ]
  ]
}

JSON true/false は 1/0、4.5 は数値になります。明示的な null と存在しない score キーはどちらも SQL NULL です。文字列 ID は変わりません。

CSV を JSON 参照表に LEFT JOIN する

{
  "sources": [
    {
      "name": "orders",
      "format": "csv",
      "text": "order_id,customer_id,total\nA100,001,12.50\nA101,002,0\nA102,009,7",
      "delimiter": ",",
      "header": true
    },
    {
      "name": "customers",
      "format": "json",
      "text": "[{\"id\":\"001\",\"name\":\"Alice\"},{\"id\":\"002\",\"name\":\"ボブ\"}]",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT o.order_id, c.name, o.total FROM orders AS o LEFT JOIN customers AS c ON o.customer_id = c.id ORDER BY o.order_id",
  "safe": true
}
{
  "columns": [
    "order_id",
    "name",
    "total"
  ],
  "rows": [
    [
      "A100",
      "Alice",
      "12.50"
    ],
    [
      "A101",
      "ボブ",
      "0"
    ],
    [
      "A102",
      null,
      "7"
    ]
  ]
}

顧客 ID は両ソースで文字列です。対応のない注文 A102 も顧客名 NULL で残り、元の total は文字列のままです。

検証済みの整数金額をグループ別に合計する

{
  "sources": [
    {
      "name": "sales",
      "format": "csv",
      "text": "region,amount\nEast,10\nWest,7\nEast,20",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT region, SUM(CAST(amount AS INTEGER)) AS total, COUNT(*) AS records FROM sales GROUP BY region ORDER BY region",
  "safe": true
}
{
  "columns": [
    "region",
    "total",
    "records"
  ],
  "rows": [
    [
      "East",
      30,
      2
    ],
    [
      "West",
      7,
      1
    ]
  ]
}

SUM の前に amount を明示的に整数へ変換します。East は 2 レコードで合計 30、West は 1 レコードで 7 です。この例は整数を使い、正確な十進演算を保証するものではありません。

WITH クエリで集計結果を絞り込む

{
  "sources": [
    {
      "name": "sales",
      "format": "csv",
      "text": "region,amount\nEast,10\nWest,7\nEast,20",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "WITH totals AS (SELECT region, SUM(CAST(amount AS INTEGER)) AS total FROM sales GROUP BY region) SELECT region, total FROM totals WHERE total >= 10 ORDER BY region",
  "safe": true
}
{
  "columns": [
    "region",
    "total"
  ],
  "rows": [
    [
      "East",
      30
    ]
  ]
}

共通テーブル式で地域別合計を求め、外側の SELECT で 10 以上だけを残します。WITH は単一の参照文の一部です。

元の表記を保ちながら数値順に並べる

{
  "sources": [
    {
      "name": "items",
      "format": "csv",
      "text": "id,quantity\nA,10\nB,2\nC,001",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT id, quantity, CAST(quantity AS INTEGER) AS numeric_quantity FROM items ORDER BY CAST(quantity AS INTEGER), id",
  "safe": true
}
{
  "columns": [
    "id",
    "quantity",
    "numeric_quantity"
  ],
  "rows": [
    [
      "C",
      "001",
      1
    ],
    [
      "B",
      "2",
      2
    ],
    [
      "A",
      "10",
      10
    ]
  ]
}

CAST で数値順と数値出力列を作ります。元の数量 001 はそのまま残り、数値としての解釈 1 を併記します。

空白や Unicode を含む識別子を引用する

{
  "sources": [
    {
      "name": "商品",
      "format": "csv",
      "text": "名称,unit price\n猫,12.50",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT \"名称\", \"unit price\" AS price FROM \"商品\"",
  "safe": true
}
{
  "columns": [
    "名称",
    "price"
  ],
  "rows": [
    [
      "猫",
      "12.50"
    ]
  ]
}

二重引用符はテーブル 商品 と列 unit price を識別します。猫 と価格文字列 12.50 は変わりません。単一引用符なら文字列リテラルになります。

引用された複数行 CSV フィールドを検索する

{
  "sources": [
    {
      "name": "notes",
      "format": "csv",
      "text": "id,note\n001,\"first\nsecond\"\n002,\"comma, quote \"\"ok\"\"\"",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT id, note FROM notes ORDER BY id",
  "safe": true
}
{
  "columns": [
    "id",
    "note"
  ],
  "rows": [
    [
      "001",
      "first\nsecond"
    ],
    [
      "002",
      "comma, quote \"ok\""
    ]
  ]
}

CSV レコードの境界を正しく解釈します。最初のメモの改行は一つの値の一部で、二重に書かれた引用符は実際の引用符になります。

NULL と空文字を別々に数える

{
  "sources": [
    {
      "name": "entries",
      "format": "json",
      "text": "[{\"id\":\"A\",\"value\":\"\"},{\"id\":\"B\",\"value\":null},{\"id\":\"C\"}]",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT COUNT(*) AS records, COUNT(value) AS non_null, SUM(value IS NULL) AS nulls FROM entries",
  "safe": true
}
{
  "columns": [
    "records",
    "non_null",
    "nulls"
  ],
  "rows": [
    [
      3,
      1,
      2
    ]
  ]
}

全 3 行のうち、NULL ではない値は空文字の 1 件です。明示的な JSON null と欠損キーの両方が IS NULL に一致します。

ヘッダーなし CSV の自動列名を使う

{
  "sources": [
    {
      "name": "people",
      "format": "csv",
      "text": "001;Paris\n002;東京",
      "delimiter": ";",
      "header": false
    }
  ],
  "sql": "SELECT column1 AS id, column2 AS city FROM people ORDER BY column1",
  "safe": true
}
{
  "columns": [
    "id",
    "city"
  ],
  "rows": [
    [
      "001",
      "Paris"
    ],
    [
      "002",
      "東京"
    ]
  ]
}

ヘッダーを無効にし、セミコロンを指定すると両行がデータになります。列名は column1 と column2 になり、SELECT の別名で分かりやすい結果見出しを付けます。

数式に見えるヘッダーと値を既定で保護する

{
  "sources": [
    {
      "name": "sheet",
      "format": "csv",
      "text": "note,total\n=1+1,-42\n@SUM(A1),0",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT note AS \"=header\", total FROM sheet ORDER BY total",
  "safe": true
}
{
  "columns": [
    "=header",
    "total"
  ],
  "rows": [
    [
      "=1+1",
      "-42"
    ],
    [
      "@SUM(A1)",
      "0"
    ]
  ],
  "csvRecords": [
    [
      "'=header",
      "total"
    ],
    [
      "'=1+1",
      "'-42"
    ],
    [
      "'@SUM(A1)",
      "0"
    ]
  ]
}

クエリ結果行は変わりません。csvRecords は =header、数式に見える文字列、-42 に出力時のアポストロフィが付くことを示します。CSV の通常の引用符だけでは数式を防げません。

信頼できる用途で元の値の CSV を明示的に選ぶ

{
  "sources": [
    {
      "name": "sheet",
      "format": "csv",
      "text": "note,total\n=1+1,-42",
      "delimiter": ",",
      "header": true
    }
  ],
  "sql": "SELECT note AS \"=header\", total FROM sheet",
  "safe": false
}
{
  "columns": [
    "=header",
    "total"
  ],
  "rows": [
    [
      "=1+1",
      "-42"
    ]
  ],
  "csvRecords": [
    [
      "=header",
      "total"
    ],
    [
      "=1+1",
      "-42"
    ]
  ]
}

safe が false なら csvRecords は結果とヘッダーの元の値に一致します。表計算ソフトで数式が実行される場合があるため、無対策の出力は慎重に選んでください。

ローカル SQL でよくある間違い

  • CSV の数値文字列を、最初から数値型の列であるかのように比較・並べ替えする。
  • CAST を検証の代わりに使い、不正な数値文字列を意図せずゼロに変換する。
  • IS NULL の代わりに = NULL を使う、または COUNT(column) を全行数と考える。
  • 一意でないキーを結合し、結果行が想定以上に増える。
  • 列名を識別子用の二重引用符ではなく単一引用符で囲む。
  • 入れ子や重複キーの JSON、または JavaScript の安全範囲外の整数を引用符なしで読み込む。
  • キャンセル後もテーブルが残る、または上限超過で失敗したクエリを部分出力できると思い込む。
  • 信頼できない無対策 CSV を表計算ソフトで開く、または CSV の引用符で数式を防げると考える。

制限と注意事項

  • 各ソースは元ファイル 2 MiB、デコード後の UTF-8 テキスト 2 MiB、データ 10,000 行、128 列、200,000 セルまでです。セッションは最大 8 テーブル、元ソースの合計 8 MiB とデコード後の UTF-8 テキストの合計 8 MiB、50,000 行、500,000 セルです。テーブル名と列名は空白のみを不可とし、最大 128 UTF-8 バイトです。ASCII の大文字小文字だけが違う名前は重複扱いで、sqlite_ で始まるテーブル名は予約済みです。SQLite のネイティブ割り当ては 64 MiB、データベースページは 32 MiB が上限です。解析済み入力、JavaScript のコピー、Worker メッセージは別途メモリーを使うため、ブラウザー全体のヒープ上限ではありません。
  • ファイルには UTF-8・UTF-16LE・UTF-16BE を明示的に指定し、不正なバイトや矛盾する BOM は拒否します。CSV は指定した区切りを使います。列数が不揃いの行、不正な引用符、空白または重複ヘッダーは読み込みエラーになります。区切りや旧来の文字コードの自動判別はしません。ヘッダーなしの列は column1、column2 などになります。CSV の値は空文字や数字に見える ID も TEXT のままです。値の暗黙変更を防ぐため、読み込むテキストの NUL 文字や不対の UTF-16 サロゲートは拒否します。JSON はフラットなオブジェクト配列を受け付け、キーを初出順に統合し、欠損と JSON null を SQL NULL、真偽値を 1/0 にします。入れ子、重複キー、安全範囲外の整数、精度を失う未対応の数値表記は拒否します。正確な ID や小数は引用符付き JSON 文字列にしてください。
  • クエリは SQLite 構文の単一 SELECT または WITH…SELECT で、最大 20,000 UTF-8 バイトです。書き込み、PRAGMA、ATTACH、SQL 拡張、ファイル・ネットワークアクセス、バインドパラメーター、複数文は使えません。結果は最大 1,000 行、128 列、50,000 セル、合計 2 MiB、1 セル 256 KiB です。どれかを超えるとクエリ全体が失敗し、部分結果や出力は残りません。WHERE を絞る、選択列を減らす、LIMIT を付けるなどで調整してください。プレビューは 1 ページ 25 行、最大 12 列、1 セル 500 文字です。正常な出力には上限内の全結果が含まれます。
  • 変換と比較は SQLite の規則に従います。無効な数値文字列が CAST でゼロになる場合があり、符号付き 64 ビット範囲外の INTEGER 変換は端の値に飽和するため、計算前に値を検証してください。小数演算は二進浮動小数点であり、正確な十進会計計算ではありません。JavaScript の安全整数範囲を超える 64 ビット整数の結果は正確な十進文字列で表します。BLOB の結果は生バイトではなく大文字の X'hex' テキストとして表示・出力します。ORDER BY がなければ行順は保証されません。結合キーの重複は行数を増やします。LIMIT は返す行数を制限しますが、低負荷なクエリを保証しません。
  • CSV 出力は最大 6 MiB、UTF-8、カンマ区切り、引用符付きフィールド、CRLF のレコード区切りで、sql-result.csv としてダウンロードします。SQL NULL は空フィールドになり、空文字との違いが失われます。数式対策は負数を含む危険なヘッダーや値にアポストロフィを付け、意図的に出力値を変えます。表計算ソフトのすべての解釈を防ぐものではなく、無対策の CSV は数式実行や ID 変換につながる場合があります。各読み込み・クエリ・ページ取得・出力の制限時間は 10 秒です。キャンセル、タイムアウト、Worker 障害、ソース編集、リセット、画面移動ですべてのテーブルと結果を破棄しますが、個人情報を含む可能性のあるダウンロードは端末に残ります。このツールはデータベースファイル、外部拡張、リモートテーブル、保存されたクエリ履歴を作成しません。

よくある質問

CSV の ORDER BY で 10 が 2 より先になるのはなぜですか?

001 などの ID の元の表記を保つため、CSV 列は文字列として読み込みます。文字列の順序は文字単位で比較します。検証済みの数値なら ORDER BY CAST(quantity AS INTEGER) や CAST(amount AS REAL) を使えます。元の表記が重要なら SELECT に元の列も残してください。CAST は検証処理ではなく、不正な数値文字列がゼロになる場合があります。

CSV の空フィールドと JSON null はどう違いますか?

CSV の空フィールドは空文字列です。JSON null とオブジェクトに存在しないキーは SQL NULL になり、true と false は 1 と 0 になります。= NULL ではなく IS NULL を使ってください。COUNT(column) は NULL を除外し、COUNT(*) は行を数えます。CSV 出力では NULL も空文字も空フィールドになるため、ダウンロード後には区別できません。

テーブルの変更、データベースファイル、SQL パラメーターは使えますか?

読み込み操作でローカルの一時テーブルを作成しますが、入力 SQL は単一の参照クエリに制限されます。上限内で SELECT、結合、集計、WITH…SELECT に対応します。INSERT、UPDATE、DELETE、CREATE、DROP、PRAGMA、ATTACH、バインドパラメーター、拡張読み込みは拒否します。SQLite データベースファイルや Parquet ファイルは開けません。また SQLite SQL は他のすべてのデータベース方言と互換ではありません。

キャンセルした場合や結果が大きすぎる場合はどうなりますか?

キャンセルは Worker を終了し、実行中クエリだけでなく一時データベースと全テーブルを解放します。リセットや画面移動でもセッションを破棄するため、続けるには再読み込みが必要です。結果が行・列・セル・バイトの上限を超えると、部分ダウンロードを出さずに失敗します。絞り込み、選択列の削減、明示的な LIMIT を使ってください。プレビューだけの省略は、正常な出力を短くしません。

関連ツール