はじめに:「サブクエリが1行を返すはずなのに複数行返ってきたよ!」と怒られる話
こんにちは!Snowflakeで SELECT 文や UPDATE 文を書いているときに、こんなエラーメッセージに出会ったことはありませんか?
Single-row subquery returns more than one row.
直訳すると「単一行を返すはずのサブクエリが、複数行を返してしまったよ」というメッセージです。SQLを書き始めたばかりの方が一度はぶつかる、いわば「サブクエリの登竜門エラー」とも言える存在ですね。
この記事では、なぜこのエラーが出るのか、そしてどう修正すれば安全に解決できるのかを、初心者の方にもわかるようにやさしく解説していきます。一緒に見ていきましょう!

エラーの正体:なぜ「1行だけ」を期待されているの?
SQLのサブクエリには、「スカラーサブクエリ」と呼ばれる種類があります。これは「値をひとつだけ返すサブクエリ」のことで、=, <, > などの比較演算子の右側に書いたり、SELECT句の中に直接埋め込んだりするタイプです。
例えば、こんなクエリを書いたとしましょう。
SELECT *
FROM orders
WHERE customer_id = (
SELECT customer_id
FROM customers
WHERE region = 'TOKYO'
);
このとき、Snowflakeは「= の右側は値ひとつだよね?」と思っています。でも、東京にいる顧客が複数いる場合、サブクエリは複数行を返してきます。そこで「1個を期待してたのに複数来たよ!」とエラーになるわけですね。
修正方法1:複数行を許容する IN 句に変える
そもそも「複数の顧客を対象にしたい」のなら、 = ではなく IN を使うのが正解です。
SELECT *
FROM orders
WHERE customer_id IN (
SELECT customer_id
FROM customers
WHERE region = 'TOKYO'
);
IN は「リストの中のいずれかに一致するか」を判定する演算子なので、サブクエリが何行返してきても問題なく動きます。ロジック的に「該当する全員」を取りたいケースでは、これが一番自然な書き方ですね。
修正方法2:MAX や MIN で1行に集約する
「最新の1件だけ」「最大金額の1件だけ」を取りたい場面では、集約関数を使ってサブクエリを強制的に1行にしてしまう方法が有効です。
SELECT *
FROM orders
WHERE order_date = (
SELECT MAX(order_date)
FROM orders
WHERE customer_id = 100
);
MAX(), MIN(), COUNT(), SUM() といった集約関数は必ず1行を返してくれるので、スカラーサブクエリとして安心して使えます。「最新日付のレコードだけ抽出したい」みたいなユースケースで頻出のパターンです。

修正方法3:相関サブクエリで行ごとに1件に絞る
「顧客ごとの最新注文を取りたい」のように、外側のテーブルの値ごとに1行ずつ評価したい場面では「相関サブクエリ」が便利です。サブクエリの中で外側のテーブルの列を参照する書き方ですね。
SELECT o.*
FROM orders o
WHERE o.order_date = (
SELECT MAX(o2.order_date)
FROM orders o2
WHERE o2.customer_id = o.customer_id
);
外側の o.customer_id をサブクエリ内で参照することで、顧客ごとに最大日付を計算し、その行だけを残せます。QUALIFY と ROW_NUMBER() を使うのもオシャレな書き方ですよ。
SELECT *
FROM orders
QUALIFY ROW_NUMBER() OVER (
PARTITION BY customer_id ORDER BY order_date DESC
) = 1;
つまずきポイントと注意点
- UPDATE 文の SET 句にサブクエリを書くときも要注意。1顧客に複数のレコードが紐づくと同じエラーになります。
- 「絶対に1行しか返らないはず」と思っていても、データの増加で突然エラーになることがあります。本番運用では MAX や LIMIT 1 で防御的に書くのがおすすめです。
- このエラーは構文エラーではなく実行時エラーなので、テストデータでは出ず本番で初めて出ることも。日付フォーマットのトラブル(Date is not recognizedエラー)や識別子トラブル(Invalid identifierエラー)と同じく、SQLを書く際の典型的な落とし穴です。
まとめ
「Single-row subquery returns more than one row」エラーは、= や < の右側に置いたサブクエリが2行以上返してしまうことで発生します。修正の選択肢は主に3つです。
- 複数行に該当させたいなら IN 句に変える
- 1行に絞り込みたいなら MAX/MIN などの集約関数で囲む
- 外側の行ごとに1件評価したいなら 相関サブクエリや QUALIFY + ROW_NUMBER() を使う
サブクエリの「何行返ってくるか」を意識する癖がつくと、SQLが一気に書きやすくなります。エラーに出会ったときこそスキルアップのチャンスです、ぜひ恐れずに対処していきましょう!
参考リンク
関連記事
- Snowflake「Date is not recognized」エラーの原因とTO_DATE/TRY_TO_DATEの使い分け – 日付変換でつまずいたときの対処法
- Snowflake「Invalid identifier」エラーの原因と解決法 – 識別子エラーの落とし穴をまとめた記事
- Object does not exist or not authorized エラーの正体 – テーブルが見えないときの最短デバッグ
- Snowflakeクエリ最適化ベストプラクティス10選 – 安全で速いSQLを書くためのコツ


