SORT / SORTBY:数式で動的に「並び替え」を実現する

💡 やりたいこと

「データベースから抽出した結果を、売上の高い順(降順)に自動で並べたい」
「わざわざデータ表にフィルターをかけて、手動で[昇順に並び替え]ボタンを押す作業をなくしたい」

新関数での解決法:SORT / SORTBY

SORT関数もまた、従来は手作業(またはマクロ)でしかできなかったアクションを「関数ベースで全自動化」した革命的なスピル関数の1つです。
元データが更新されれば、抽出先の一覧も自動的に「常にソートされ直した状態」を保ちます。

SORT(配列の中の列番号を基準に並び替え)

=SORT(配列, [並び替えの基準列番号], [順序: 1昇順/-1降順], [列方向: TRUE/FALSE])
=SORT(A2:E1000, 5, -1)

意味:A2:E1000の範囲を、左から5番目の列(E列=売上など)の値を基準にして「-1(降順=大きい順)」に並び替える。

SORTBY(配列「外」の範囲も含めて複数条件で並び替え)

SORT単体では「複数の列を基準にしたソート(第1キーは部署順、第2キーは売上順など)」がやりにくいですが、SORTBYを使えば自在です。

=SORTBY(配列, 基準配列1, [順序1], 基準配列2, [順序2], ...)
=SORTBY(A2:E1000, B2:B1000, 1, E2:E1000, -1)

意味:A2:E1000を、まず「B列(部署)の昇順」で並べ、次にその中で「E列(売上)の降順」で並べる。
※SORTBYは列番号での指定ではなく、範囲そのもの(B2:B1000など)で指定するのが特徴。

🔥 FILTER・UNIQUEとの合わせ技(THE・神コンボ)
=SORT(UNIQUE(A:A)) (マスタ一覧をあいうえお順に)
=TAKE(SORT(FILTER(A2:E100, B2:B100="東京"), 5, -1), 10)
(東京のデータだけを抽出し、売上の高い順に並び替え、その上位10件だけを表示する)
このように、関数をマトリョーシカのように入れ子(ネスト)にしていくことで、VBAで数十行書かざるを得なかった集計処理が1行で完結します。

🔍 SORT vs SORTBY ── どう使い分ける?

① 2つの関数の引数を並べて比較

データテーブル
比較項目 SORT SORTBY
基準列の指定方法 列「番号」で指定
=SORT(A:E, 3, -1)
← 3列目で降順
列「範囲」で指定
=SORTBY(A:E, C:C, -1)
← C列で降順
複数キーのソート 配列定数で可能だが
やや書きにくい
=SORT(A:E, {3,5}, {1,-1})
引数をペアで追加するだけ
直感的で読みやすい
=SORTBY(A:E, C:C, 1, E:E, -1)
配列「外」の値でソート ❌ 不可
(配列内の列しか基準にできない)
✅ 可能
(別シートの列や計算式も基準にできる)
計算値でソート
(文字数・月日など)
❌ 不可 ✅ 可能
=SORTBY(A:B, LEN(A:A))
カスタム順序でソート
(高・中・低 など)
❌ 不可 ✅ 可能
MATCH/XMATCHと組み合わせ
横方向(列方向)のソート 第4引数 TRUE で明示指定 基準配列の形状から自動判定
列の追加・削除への耐性 弱い(列番号がズレる) 強い(範囲参照なのでズレない)
💡 使い分けの結論
「単純な1列ソート」→ SORT で十分(最も短く書ける)
「複数キー / 計算値 / カスタム順序 / 配列外の基準」→ SORTBY 一択

📘 SORT関数 ── 引数と挙動を深掘り

② 全4引数の詳細

データテーブル
引数 必須? 説明 既定値
配列 必須 ソート対象のセル範囲 or 配列
sort_index 任意 何列目(横方向なら何行目)を基準にするか 1(先頭列)
sort_order 任意 1 = 昇順(A→Z / 小→大)
-1 = 降順(Z→A / 大→小)
1(昇順)
by_col 任意 TRUE = 列方向(横)にソート
FALSE = 行方向(縦)にソート
FALSE(行方向)

③ 基本例:1列ソート(名前を五十音順に)

データテーブル
ABDE
1名前売上名前売上
2田中500伊藤180
3佐藤320加藤210
4伊藤180佐藤320
5山田410田中500
6加藤210山田410
=SORT(A2:B6)

D2に入力 → D2:E6にスピル。引数省略で「1列目の昇順」。名前の五十音(文字コード)順に全列がまとめて並び替わります。

④ 売上の降順でソート

=SORT(A2:B6, 2, -1)
データテーブル
DE
2田中500
3山田410
4佐藤320
5加藤210
6伊藤180

2列目(売上)を基準に降順。ランキング表の自動生成に直結します。

⑤ 複数キーのソート(配列定数を使う方法)

SORTで複数列を基準にするには、sort_index と sort_order に 配列定数 {} を使います。

データテーブル
ABC
1部署名前売上
2営業田中500
3開発佐藤320
4営業伊藤180
5開発山田410
6営業加藤210
=SORT(A2:C6, {1,3}, {1,-1})

第1キー:1列目(部署)を昇順 → 第2キー:3列目(売上)を降順。
結果:営業グループの中では売上の高い順、開発グループの中でも売上の高い順に並ぶ。

データテーブル
EFG← 結果
2営業田中500
3営業加藤210
4営業伊藤180
5開発山田410
6開発佐藤320
⚠️ 配列定数 {1,3}{1,-1} の対応
{1,3} の「1」が部署列(昇順1)、「3」が売上列(降順-1)に対応。
順序と基準が1対1で対応しているので、数が一致しないとエラーになります。

📗 SORTBY関数 ── SORTにはできない技

⑥ SORTBYの複数キーソート(より直感的)

上記と同じ「部署昇順 → 売上降順」を SORTBYで書くとこうなります。

=SORTBY(A2:C6, A2:A6, 1, C2:C6, -1)

配列定数ではなく「範囲, 順序」のペアを繰り返すだけ。列の追加・削除があっても列番号がズレないので保守性が高い。

⑦ 計算値でソート:文字数順

「名前の短い順に並べたい」など、データそのものにはない「計算した値」を基準にする場合、SORTBYの独壇場です。

データテーブル
AC
1国名結果
2JapanCuba
3AustraliaJapan
4CubaFrance
5FranceAustralia
=SORTBY(A2:A5, LEN(A2:A5))

LEN(文字数)の結果を基準にソート。Cuba(4) → Japan(5) → France(6) → Australia(9) の順になる。

⑧ カスタム順序ソート(高→中→低 など)

「高・中・低」のような独自の優先順位で並べたい場合、XMATCH(またはMATCH)で順位を数値化し、それを基準にSORTBYへ渡します。

データテーブル
ABD
1タスク優先度順序マスタ
2レポート作成
3顧客対応
4資料整理
5見積提出
=SORTBY(A2:B5, XMATCH(B2:B5, D2:D4))

XMATCH がマスタ内の位置番号(高=1, 中=2, 低=3)を返し、SORTBYがその数値順に並べる。
結果:顧客対応(高) → 見積提出(高) → 資料整理(中) → レポート作成(低)

⑨ ランダムシャッフル

=SORTBY(A2:A10, RANDARRAY(ROWS(A2:A10)))

RANDARRAYが乱数を生成し、SORTBYがその乱数の小さい順に並べる → 毎回ランダムな順序になる。
抽選・座席シャッフルなどに便利。シートを再計算するたびに順序が変わります。

⑩ 日付の月日だけでソート(誕生日カレンダー)

=SORTBY(A2:B10, TEXT(B2:B10, "mmdd"))

TEXT関数で月日だけを "0718" のような文字列に変換し、それを基準にソート。
年を無視した「カレンダー順」が実現できる。

🔒 知っておくべき:安定ソート(Stable Sort)

SORT・SORTBYはどちらも「安定ソート」です。これは「ソート基準の値が同じ行は、元データでの並び順がそのまま維持される」ということを意味します。

データテーブル
ABDE
1名前部署名前部署
2田中営業田中営業
3佐藤開発伊藤営業
4伊藤営業佐藤開発
5山田開発山田開発
=SORT(A2:B5, 2, 1)

部署の昇順でソート。営業が2人(田中・伊藤)いるが、元データの並び順(田中→伊藤)がそのまま維持される。
これが「安定ソート」。旧来の LARGE+INDEX+MATCH では実現が困難でした。

🚀 他の関数との組み合わせ ── 実務の神コンボ集

SORT / SORTBY の真価は、他のスピル関数と組み合わせたときに発揮されます。ここからが本番です。

コンボ① FILTER + SORT:条件抽出 → 並び替え

最も使用頻度が高い鉄板の組み合わせ。FILTERで絞り込んだ結果を、そのままSORT(またはSORTBY)に渡します。

データテーブル
ABCD
1地域商品売上
2東京PC5004月
3大阪モニター2004月
4東京キーボード805月
5東京マウス304月
6大阪PC4505月
7東京モニター3505月
=SORT(FILTER(A2:D7, A2:A7="東京"), 3, -1)
データテーブル
FGHI← 結果
2東京PC5004月
3東京モニター3505月
4東京キーボード805月
5東京マウス304月

FILTERで東京だけ抽出 → SORTで3列目(売上)の降順に並び替え。
元データが追加されても自動で再計算されます。

💡 SORTBYでFILTER結果を並べる場合の注意
SORTBYの基準配列はFILTER後の配列と同じサイズでなければなりません。
=SORTBY(FILTER(A2:D7, A2:A7="東京"), FILTER(C2:C7, A2:A7="東京"), -1)
このように、基準配列にも同じFILTERを適用する必要があります。
面倒な場合は SORT(..., 列番号, 順序) の方が簡潔です。

コンボ② FILTER + SORT + TAKE:Top N 抽出(上位○件)

=TAKE(SORT(FILTER(A2:D7, A2:A7="東京"), 3, -1), 3)

東京のデータを売上降順に並べ、上位3件だけを返す。
TAKEの第2引数が取得行数。マイナスにすると末尾から取得できます。

データテーブル
FGHI
2東京PC5004月
3東京モニター3505月
4東京キーボード805月

コンボ③ UNIQUE + SORT:重複排除 → 五十音順マスタ

=SORT(UNIQUE(B2:B100))

B列から重複を除去し、昇順に並べる。
ドロップダウンリスト(入力規則)のソースや、集計用のマスタ一覧の自動生成に最適。

=SORT(UNIQUE(A2:C100), 3, -1)

複数列の組み合わせで重複排除し、3列目の降順でソート。

コンボ④ XLOOKUP + SORT:検索結果をソートして表示

XLOOKUPが複数列を返す場合、その結果をさらにSORT / SORTBYで並べ替えるパターンです。

データテーブル
ABCDE
1社員ID名前4月5月6月
2E001田中120150180
3E002佐藤200180220
4E003伊藤90110100

「E002の月別売上を降順で見たい」場合:

=SORT(XLOOKUP("E002", A2:A4, C2:E4), , -1, TRUE)

XLOOKUPで E002 の行(200, 180, 220)を横方向に取得。
SORTの第4引数 TRUE で横方向ソート → 220, 200, 180 の降順で返る。

コンボ⑤ SORTBY + XLOOKUP:別テーブルの値を基準にソート

SORTBYの基準配列にXLOOKUPを入れると、「別テーブルにある値を基準にして、手元のテーブルを並べ替える」ことができます。

データテーブル
AB DE
1商品ID在庫数 商品ID優先度
2P-10125 P-1013
3P-20542 P-2051
4P-312150 P-3122
=SORTBY(A2:B4, XLOOKUP(A2:A4, D2:D4, E2:E4))

XLOOKUPが各商品IDの優先度(1, 2, 3)を返し、SORTBYがその値で昇順ソート。
結果:P-205(優先度1) → P-312(優先度2) → P-101(優先度3) の順に並ぶ。
在庫テーブルに「優先度」列を追加しなくても、別テーブルの値で並べ替えられるのがポイント。

コンボ⑥ FILTER + SORT + UNIQUE:フル・コンボ

=SORT(UNIQUE(FILTER(A2:C100, B2:B100="営業")), 3, -1)

① FILTER で「営業」部門だけを抽出
② UNIQUE で重複行を排除
③ SORT で 3列目(売上)の降順に並べ替え
→ 営業部門のユニークなデータが売上順で一覧になる。

コンボ⑦ LET + SORT:複雑な数式を読みやすく

ネストが深くなったら LET関数で中間結果に名前をつけると格段に読みやすくなります。

=LET( data, A2:D100, filtered, FILTER(data, INDEX(data,,1)="東京"), sorted, SORT(filtered, 3, -1), TAKE(sorted, 10) )

LET関数で data → filtered → sorted と名前をつけて段階的に処理。
最終行の TAKE(sorted, 10) で上位10件を返す。
やっていることは「=TAKE(SORT(FILTER(...),3,-1),10)」と同じだが、読みやすさが段違い。

⚠️ よくあるエラーと注意点

データテーブル
エラー 原因 対処法
#SPILL! スピル先のセルに値が入っている 出力先を空にする
#VALUE! sort_index が範囲外 / SORTBYの基準配列サイズ不一致 列番号・配列サイズを確認
#CALC! FILTERの結果が0件(空配列) FILTERの第3引数(if_empty)を設定:
FILTER(..., ..., "該当なし")
#REF! 参照先のブックが閉じている 参照先ブックを開く
⚠️ ヘッダーを含めないこと
SORT / SORTBY はすべての行を「データ」として扱います。A1:D100 のようにヘッダー行を含めると、ヘッダーもソート対象になり意図しない結果になります。
必ず A2:D100 のようにデータ行だけを指定してください。
⚠️ 範囲の自動拡張について
=SORT(A2:D100, 3, -1) のように固定範囲を指定すると、101行目以降にデータを追加しても反映されません。
自動拡張させたい場合はExcelテーブル(Ctrl+T)を使うか、TRIMRANGE 関数(対応環境のみ)で動的範囲を作成してください。

旧バージョンでの代替法(LARGE / RANK)

SORT登場以前、数式だけで「トップ10の表を自動更新させる」のは至難の業でした。

⚠️ 旧来の手法:LARGE関数で数値を取り、INDEX+MATCHで紐付け
=LARGE(売上範囲, ROW(A1)) で1位、2位の売上高を取り出し、それをキーにして =INDEX(名前範囲, MATCH(1位の売上高, 売上範囲, 0)) とやって「誰の売上か」を照合・抽出する手法。

この旧来手法には「同率1位(同じ売上高)の人が複数いると、数式が先に見つけた1人目の名前ばかりを重複して取得してしまう」という致命的な欠陥がありました。これを回避するためには「売上データの末尾に +ROW()/100000 のように微小な行番号をわざと足して、無理やり数値を一意にずらす」といったトリッキーな細工(作業列)が必要不可欠でした。

現在のSORT関数を使えば、同率タイの順位も「元データの並び順」を維持して正しく全員分表示してくれます(安定ソート)。

📌 まとめ:SORT / SORTBY 使い分けチャート

Q. ソート基準は配列「内」の列?
 ├ YES → 単一キー? → SORT(配列, 列番号, 順序)
 ├ YES → 複数キー? → SORT(配列, {列1,列2}, {順1,順2}) or SORTBY
 └ NO(配列外 / 計算値 / カスタム順序) → SORTBY 一択

Q. 他の関数と組み合わせる?
 ├ 条件抽出 → FILTER + SORT
 ├ 重複排除 → UNIQUE + SORT
 ├ 上位N件 → FILTER + SORT + TAKE
 ├ 別テーブルの値で並べ替え → SORTBY + XLOOKUP
 └ 数式が長い → LET で中間変数を定義して可読性UP

Q. 大規模データの検索が遅い?
 ├ 作業シートに SORT でソート済みデータを1回スピル
 └ XLOOKUP / XMATCH の search_mode = 2 でバイナリ検索 → 爆速化
💡 最後に
SORT / SORTBY は「手作業の並び替え」を完全に関数化した、スピル時代を代表する関数です。FILTER・UNIQUE・TAKE・XLOOKUP・LET と組み合わせることで、従来はVBAで何十行も書いていた集計処理がたった1行の数式で完結します。

さらに、SORT で作ったソート済みデータは XLOOKUP / XMATCH のバイナリ検索モードの「燃料」になります。大規模データの検索速度に悩んでいるなら、SORT + バイナリ検索のアーキテクチャを今日から試してみてください。

🔗 関連記事