ウィンドウ関数とは、行をまとめずに(行数を減らさずに)、各行に「グループ内の順位・合計・前の行の値」などを付け足せるSQLの関数です。関数() OVER (PARTITION BY ... ORDER BY ...) の形で書き、累計、移動平均、前月比、グループごとの上位N件といった集計を、1本のSQLで書けるようになります。

この記事では、基本の書き方から、ROW_NUMBER・RANK・DENSE_RANK の違い、LAG を使った前月比、ORDER BYを付けたときの既定のフレーム(RANGE)で累計がずれる落とし穴、ウィンドウ関数を WHERE で使えない理由までを、PostgreSQL 16.13で実際にテーブルを作って実行した結果つきで解説します。MySQL・SQL Server・SQLiteなどDB別の対応状況もまとめます。

ウィンドウ関数の早見表

やりたいこと 書き方
行を残したまま、グループの合計を並べる SUM(amount) OVER (PARTITION BY shop)
連番を振る(同点でも別の番号) ROW_NUMBER() OVER (ORDER BY score DESC)
順位(同点は同順位、次を飛ばす:1,2,2,4) RANK() OVER (...)
順位(同点は同順位、飛ばさない:1,2,2,3) DENSE_RANK() OVER (...)
累計 SUM(amount) OVER (PARTITION BY shop ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
直近3か月の移動平均 AVG(amount) OVER (... ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
前の行・次の行の値 LAG(amount) OVER (...) / LEAD(amount) OVER (...)
グループの最初・最後の値 FIRST_VALUE(...) / LAST_VALUE(...)(フレーム指定が必要)
構成比 amount * 100.0 / SUM(amount) OVER (PARTITION BY shop)
グループごとの上位N件 CTEで ROW_NUMBER() を付け、外側で WHERE rn <= N

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「SQLウィンドウ関数の使い方|累計・前月比・上位N件を実行結果で解説」

使うサンプルデータ

CREATE TABLE sales (
  id      serial PRIMARY KEY,
  month   date NOT NULL,
  shop    text NOT NULL,
  amount  integer NOT NULL
);
INSERT INTO sales (month, shop, amount) VALUES
 ('2026-01-01','東店',100),('2026-02-01','東店',120),('2026-03-01','東店',90),('2026-04-01','東店',150),
 ('2026-01-01','西店',80),('2026-02-01','西店',80),('2026-03-01','西店',110),('2026-04-01','西店',70);

CREATE TABLE scores (name text, dept text, score int);
INSERT INTO scores VALUES
 ('佐藤','開発',90),('鈴木','開発',85),('高橋','開発',85),('田中','開発',70),
 ('伊藤','営業',95),('渡辺','営業',80),('山本','営業',80);

OVER・PARTITION BY・ORDER BY の基本

GROUP BY との違い

SELECT shop, SUM(amount) AS total FROM sales GROUP BY shop;
 shop | total
------+-------
 東店 |   460
 西店 |   340
(2 rows)
SELECT month, shop, amount,
       SUM(amount) OVER (PARTITION BY shop) AS shop_total
FROM sales ORDER BY shop, month;
   month    | shop | amount | shop_total
------------+------+--------+------------
 2026-01-01 | 東店 |    100 |        460
 2026-02-01 | 東店 |    120 |        460
 2026-03-01 | 東店 |     90 |        460
 2026-04-01 | 東店 |    150 |        460
 2026-01-01 | 西店 |     80 |        340
 2026-02-01 | 西店 |     80 |        340
 2026-03-01 | 西店 |    110 |        340
 2026-04-01 | 西店 |     70 |        340
(8 rows)

GROUP BYは8行を2行にまとめますが、ウィンドウ関数は8行を残したまま、各行に店舗の合計を付け足します。「明細と合計を同時に見たい」ときに、自己結合やサブクエリが不要になります。

比較 GROUP BY ウィンドウ関数
結果の行数 グループの数に減る 元の行数のまま
明細の列 GROUP BYに書いた列と集計値だけ すべての列を使える
順位・前の行 扱えない RANK、LAG などで扱える

OVER の中の3つの要素

関数名(引数) OVER (
  PARTITION BY 区切る列      -- どの単位で分けるか(省略すると全体で1つ)
  ORDER BY 並べる列          -- どの順に並べるか
  ROWS BETWEEN ... AND ...   -- どの範囲を計算に使うか(フレーム)
)
要素 役割 省略したとき
PARTITION BY グループに分ける(GROUP BYに相当) 全行が1つのグループ
ORDER BY グループ内の並び順 順序なし(全行が同列扱い)
フレーム句 計算に使う行の範囲 ORDER BYの有無で既定値が変わる(後述)

OVER () と空にすると、全体の合計や件数を各行に付けられます。

SELECT month, shop, amount, SUM(amount) OVER () AS grand_total, COUNT(*) OVER () AS cnt
FROM sales ORDER BY month, shop LIMIT 3;
   month    | shop | amount | grand_total | cnt
------------+------+--------+-------------+-----
 2026-01-01 | 東店 |    100 |         800 |   8
 2026-01-01 | 西店 |     80 |         800 |   8
 2026-02-01 | 東店 |    120 |         800 |   8

ROW_NUMBER・RANK・DENSE_RANK の違い

SELECT dept, name, score,
  ROW_NUMBER() OVER (PARTITION BY dept ORDER BY score DESC) AS row_number,
  RANK()       OVER (PARTITION BY dept ORDER BY score DESC) AS rank,
  DENSE_RANK() OVER (PARTITION BY dept ORDER BY score DESC) AS dense_rank
FROM scores ORDER BY dept, score DESC, name;
 dept | name | score | row_number | rank | dense_rank
------+------+-------+------------+------+------------
 営業 | 伊藤 |    95 |          1 |    1 |          1
 営業 | 山本 |    80 |          2 |    2 |          2
 営業 | 渡辺 |    80 |          3 |    2 |          2
 開発 | 佐藤 |    90 |          1 |    1 |          1
 開発 | 鈴木 |    85 |          2 |    2 |          2
 開発 | 高橋 |    85 |          3 |    2 |          2
 開発 | 田中 |    70 |          4 |    4 |          3
(7 rows)
関数 同点のとき 次の番号 開発部の結果 向いている用途
ROW_NUMBER 別の番号 連続 1, 2, 3, 4 重複の除去、1件だけ取る、ページング
RANK 同じ番号 飛ばす 1, 2, 2, 4 競技の順位(「4位」が正しい場面)
DENSE_RANK 同じ番号 飛ばさない 1, 2, 2, 3 「上位3種類の点数」のような段階分け

ROW_NUMBER は同点の行にどちらが先の番号を振るかが決まっていません。上の結果で山本さんが2、渡辺さんが3になったのは偶然です。結果を毎回同じにしたいときは、ORDER BY score DESC, name のように最後に一意な列を加えます。

SUM OVER で累計を出す

SELECT shop, month, amount,
  SUM(amount) OVER (PARTITION BY shop ORDER BY month) AS running_total
FROM sales ORDER BY shop, month;
 shop |   month    | amount | running_total
------+------------+--------+---------------
 東店 | 2026-01-01 |    100 |           100
 東店 | 2026-02-01 |    120 |           220
 東店 | 2026-03-01 |     90 |           310
 東店 | 2026-04-01 |    150 |           460
 西店 | 2026-01-01 |     80 |            80
 西店 | 2026-02-01 |     80 |           160
 西店 | 2026-03-01 |    110 |           270
 西店 | 2026-04-01 |     70 |           340
(8 rows)

OVERに ORDER BY を付けると、SUMは「先頭から現在の行まで」の合計=累計になります。PARTITION BY shop で、店舗が変わると0から数え直します。ただし、この書き方には次の落とし穴があります。

ORDER BYありの既定フレームの落とし穴(RANGE と ROWS)

同じ日の注文が2件ある表で累計を出します。

CREATE TABLE orders (id int, order_date date, amount int);
INSERT INTO orders VALUES (1,'2026-09-01',100),(2,'2026-09-02',200),(3,'2026-09-02',300),(4,'2026-09-03',400);

SELECT id, order_date, amount,
  SUM(amount) OVER (ORDER BY order_date) AS sum_default,
  SUM(amount) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_rows,
  SUM(amount) OVER (ORDER BY order_date, id) AS sum_tiebreak
FROM orders ORDER BY order_date, id;
 id | order_date | amount | sum_default | sum_rows | sum_tiebreak
----+------------+--------+-------------+----------+--------------
  1 | 2026-09-01 |    100 |         100 |      100 |          100
  2 | 2026-09-02 |    200 |         600 |      300 |          300
  3 | 2026-09-02 |    300 |         600 |      600 |          600
  4 | 2026-09-03 |    400 |        1000 |     1000 |         1000
(4 rows)

id=2 の累計が、既定の書き方では 300 ではなく 600 になりました。

フレームの指定 意味 id=2 の結果
省略(ORDER BYあり) RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW と同じ。ORDER BYの値が同じ行(ピア)をまとめて含める 600
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 物理的な行の位置で「現在の行まで」 300
ORDER BYに一意な列を追加 ピアがなくなるので、RANGEでも1行ずつ 300

ORDER BYを付けたときの既定フレームは RANGE で、同じ値の行を「同時」とみなします。PostgreSQL・MySQL(公式リファレンスに明記)など、多くのDBで同じ仕様です。

目的 おすすめの書き方
行ごとに1行ずつ増える累計 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW を明示し、ORDER BYに一意な列も加える
同じ日の分はまとめて同じ累計にしたい 既定(RANGE)のままでよい

sum_rows の結果も、同じ日の2行のどちらが先かはDBが決めます。ROWSを使うときも、ORDER BYに一意な列(idなど)を加えると結果が安定します。

ORDER BYなしの既定フレーム

ORDER BYを省略すると、既定フレームはパーティション全体です。先ほどの SUM(amount) OVER (PARTITION BY shop) が店舗の合計になったのはこのためです。

移動平均(フレーム句 ROWS BETWEEN)

SELECT shop, month, amount,
  ROUND(AVG(amount) OVER (PARTITION BY shop ORDER BY month
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW), 1) AS avg_3m,
  COUNT(*) OVER (PARTITION BY shop ORDER BY month
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS n
FROM sales ORDER BY shop, month;
 shop |   month    | amount | avg_3m | n
------+------------+--------+--------+---
 東店 | 2026-01-01 |    100 |  100.0 | 1
 東店 | 2026-02-01 |    120 |  110.0 | 2
 東店 | 2026-03-01 |     90 |  103.3 | 3
 東店 | 2026-04-01 |    150 |  120.0 | 3
 西店 | 2026-01-01 |     80 |   80.0 | 1
 西店 | 2026-02-01 |     80 |   80.0 | 2
 西店 | 2026-03-01 |    110 |   90.0 | 3
 西店 | 2026-04-01 |     70 |   86.7 | 3
(8 rows)

2 PRECEDING AND CURRENT ROW は「2行前から現在の行まで」の3行です。最初の2か月は3行そろわないため、1行・2行での平均になっています(n 列)。3か月そろった行だけを使いたいときは、CASE WHEN n = 3 THEN avg_3m END のように件数で判定します。

フレームの書き方 意味
UNBOUNDED PRECEDING パーティションの先頭
n PRECEDING n行前
CURRENT ROW 現在の行
n FOLLOWING n行後
UNBOUNDED FOLLOWING パーティションの最後

行数ではなく「日付の範囲」で区切る(RANGE + INTERVAL)

データが毎日そろっていない場合、「3行」と「3日間」は一致しません。

CREATE TABLE daily (d date, amount int);
INSERT INTO daily VALUES ('2026-09-01',10),('2026-09-02',20),('2026-09-05',30),('2026-09-09',40);

SELECT d, amount,
  SUM(amount) OVER (ORDER BY d ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS rows_3,
  SUM(amount) OVER (ORDER BY d RANGE BETWEEN INTERVAL '2 days' PRECEDING AND CURRENT ROW) AS range_3days
FROM daily ORDER BY d;
     d      | amount | rows_3 | range_3days
------------+--------+--------+-------------
 2026-09-01 |     10 |     10 |          10
 2026-09-02 |     20 |     30 |          30
 2026-09-05 |     30 |     60 |          30
 2026-09-09 |     40 |     90 |          40
(4 rows)

ROWS は「3行分」、RANGE ... INTERVAL '2 days' は「当日を含む3日間」を合計します。9月5日の行では、ROWSは9月1日・2日の分まで含めて60、RANGEは3〜5日の分だけで30になりました。日付に抜けがあるデータの「直近◯日」は RANGE と INTERVAL を使います(PostgreSQL 11以降、MySQL 8.0以降で可能)。

LAG・LEAD で前月比を出す

SELECT shop, month, amount,
  LAG(amount) OVER w AS prev,
  amount - LAG(amount) OVER w AS diff,
  ROUND(100.0 * amount / LAG(amount) OVER w, 1) AS pct,
  LEAD(amount) OVER w AS next
FROM sales
WINDOW w AS (PARTITION BY shop ORDER BY month)
ORDER BY shop, month;
 shop |   month    | amount | prev | diff |  pct  | next
------+------------+--------+------+------+-------+------
 東店 | 2026-01-01 |    100 |      |      |       |  120
 東店 | 2026-02-01 |    120 |  100 |   20 | 120.0 |   90
 東店 | 2026-03-01 |     90 |  120 |  -30 |  75.0 |  150
 東店 | 2026-04-01 |    150 |   90 |   60 | 166.7 |
 西店 | 2026-01-01 |     80 |      |      |       |   80
 西店 | 2026-02-01 |     80 |   80 |    0 | 100.0 |  110
 西店 | 2026-03-01 |    110 |   80 |   30 | 137.5 |   70
 西店 | 2026-04-01 |     70 |  110 |  -40 |  63.6 |
(8 rows)

LAG は前の行、LEAD は次の行の値を返します。前の行がない最初の月は NULL になるので、差分や比率も NULL になります。

ポイント 内容
WINDOW w AS (...) 同じOVERの中身に名前を付けて使い回せる
LAG(amount, 1, 0) 2番目の引数は何行前か、3番目は前の行がないときの既定値
100.0 * 整数どうしの割り算で小数が切り捨てられるのを防ぐ
月の抜け LAGは「1行前」を返すので、データのない月があると前々月と比べてしまう。月の一覧と外部結合してから使うと確実

既定値を指定した例です。

SELECT shop, month, amount, LAG(amount, 1, 0) OVER (PARTITION BY shop ORDER BY month) AS prev0
FROM sales WHERE shop='西店' ORDER BY month;
 shop |   month    | amount | prev0
------+------------+--------+-------
 西店 | 2026-01-01 |     80 |     0
 西店 | 2026-02-01 |     80 |    80
 西店 | 2026-03-01 |    110 |    80
 西店 | 2026-04-01 |     70 |   110

FIRST_VALUE と LAST_VALUE の落とし穴

SELECT shop, month, amount,
  FIRST_VALUE(amount) OVER (PARTITION BY shop ORDER BY month) AS first_v,
  LAST_VALUE(amount)  OVER (PARTITION BY shop ORDER BY month) AS last_default,
  LAST_VALUE(amount)  OVER (PARTITION BY shop ORDER BY month
       ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_full
FROM sales ORDER BY shop, month;
 shop |   month    | amount | first_v | last_default | last_full
------+------------+--------+---------+--------------+-----------
 東店 | 2026-01-01 |    100 |     100 |          100 |       150
 東店 | 2026-02-01 |    120 |     100 |          120 |       150
 東店 | 2026-03-01 |     90 |     100 |           90 |       150
 東店 | 2026-04-01 |    150 |     100 |          150 |       150
 西店 | 2026-01-01 |     80 |      80 |           80 |        70
 西店 | 2026-02-01 |     80 |      80 |           80 |        70
 西店 | 2026-03-01 |    110 |      80 |          110 |        70
 西店 | 2026-04-01 |     70 |      80 |           70 |        70

LAST_VALUE をそのまま使うと、「最後の月」ではなく「現在の行」の値になりました。既定フレームが「現在の行まで」なので、その範囲の最後=自分自身になるからです。パーティション全体の最後の値がほしいときは、UNBOUNDED FOLLOWING までフレームを広げます。または、FIRST_VALUE(amount) OVER (PARTITION BY shop ORDER BY month DESC) と並び順を逆にする方法もあります。

WHERE で使えない理由と、上位N件の取り方

WHERE に書くとエラーになる

SELECT dept, name, score, RANK() OVER (PARTITION BY dept ORDER BY score DESC) AS rk
FROM scores WHERE RANK() OVER (PARTITION BY dept ORDER BY score DESC) <= 2;
ERROR:  window functions are not allowed in WHERE

別名で書いてもエラーです。

SELECT dept, name, score, RANK() OVER (PARTITION BY dept ORDER BY score DESC) AS rk
FROM scores WHERE rk <= 2;
ERROR:  column "rk" does not exist

SQLは FROM → WHERE → GROUP BY → HAVING → SELECT(ここでウィンドウ関数を計算)→ ORDER BY の順に処理されます。WHEREの時点では、まだ順位が計算されていません。反対に、ORDER BY は SELECT の後なので、別名 rk を使えます。

SELECT name, score, RANK() OVER (ORDER BY score DESC) AS rk FROM scores ORDER BY rk LIMIT 3;
 name | score | rk
------+-------+----
 伊藤 |    95 |  1
 佐藤 |    90 |  2
 鈴木 |    85 |  3

CTE(WITH句)で包んでから絞り込む

WITH ranked AS (
  SELECT dept, name, score,
    ROW_NUMBER() OVER (PARTITION BY dept ORDER BY score DESC, name) AS rn,
    RANK()       OVER (PARTITION BY dept ORDER BY score DESC)       AS rk
  FROM scores
)
SELECT * FROM ranked WHERE rn <= 2 ORDER BY dept, rn;
 dept | name | score | rn | rk
------+------+-------+----+----
 営業 | 伊藤 |    95 |  1 |  1
 営業 | 山本 |    80 |  2 |  2
 開発 | 佐藤 |    90 |  1 |  1
 開発 | 鈴木 |    85 |  2 |  2
(4 rows)

同じCTEで WHERE rk <= 2 にした結果です。

 dept | name | score | rk
------+------+-------+----
 営業 | 伊藤 |    95 |  1
 営業 | 山本 |    80 |  2
 営業 | 渡辺 |    80 |  2
 開発 | 佐藤 |    90 |  1
 開発 | 鈴木 |    85 |  2
 開発 | 高橋 |    85 |  2
(6 rows)
条件 同点がいるとき 件数
ROW_NUMBER() <= 2 ちょうど2件(同点の一方は外れる) 各部署2件
RANK() <= 2 同点を全員含める 2件を超えることがある

「必ずN件」なら ROW_NUMBER、「同点は全員」なら RANK と、要件で選びます。サブクエリ(SELECT * FROM (...) t WHERE rn <= 2)でも同じことができます。

Snowflake・BigQuery・DuckDBなどでは QUALIFY rn <= 2 と書いてウィンドウ関数の結果で直接絞り込めますが、PostgreSQL・MySQLには QUALIFY がないので、CTEかサブクエリを使います。

DB別の対応状況

DB ウィンドウ関数 RANGE + INTERVAL QUALIFY 補足
PostgreSQL 8.4以降 11以降 なし GROUPS・EXCLUDE も対応(11以降)
MySQL 8.0以降 8.0以降 なし 5.7以前は使えない。フレームは ROWS / RANGE
SQLite 3.25以降 未対応 なし GROUPS・EXCLUDE は3.28以降
SQL Server 2005以降(集計のORDER BY・フレームは2012以降) 未対応 なし 2022で WINDOW 句に対応
Oracle 古くから対応(分析関数) 対応 なし
BigQuery / Snowflake 対応 製品ごとに仕様が異なる あり

利用中のDBのバージョンを先に確認しておくと安心です(MySQLなら SELECT VERSION();)。基本の OVER (PARTITION BY ... ORDER BY ...) と ROW_NUMBER・RANK・LAG などは、上記のDBで共通して使えます。

性能の目安

 WindowAgg
   ->  Sort
         Sort Key: dept, score DESC
         ->  Seq Scan on scores

PostgreSQLの実行計画です。ウィンドウ関数は PARTITION BY と ORDER BY の順に並べ替え(Sort)てから計算します。大きな表では、(dept, score DESC) のような複合インデックスで並べ替えを省ける場合があります。また、OVERの中身が同じ関数は1回の並べ替えでまとめて計算されるので、WINDOW 句で共通化しておくと読みやすさも保てます。

よくある失敗と直し方

症状 原因 直し方
累計が同じ値の行で飛ぶ ORDER BYありの既定フレームが RANGE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW、ORDER BYに一意な列
LAST_VALUE が自分の値になる 既定フレームが「現在の行まで」 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
window functions are not allowed in WHERE WHEREはSELECTより先に処理される CTE・サブクエリで包む
上位N件の結果が実行ごとに変わる 同点の順序が未定義 ORDER BYに一意な列を追加
前月比が前々月と比べている データのない月がある 月の一覧と外部結合してからLAG
比率が0になる 整数どうしの割り算 100.0 * や ::numeric で小数に
移動平均の最初の月が小さい行数で計算される フレーム内の行が足りない COUNT(*) OVER (同じフレーム) で件数を確認

よくある質問

Q. GROUP BY とウィンドウ関数は一緒に使えますか? A. 使えます。GROUP BYで集計した結果に対して、ウィンドウ関数が計算されます。たとえば SELECT shop, SUM(amount), RANK() OVER (ORDER BY SUM(amount) DESC) FROM sales GROUP BY shop で、店舗の売上合計の順位を出せます。

Q. ROWS と RANGE はどちらを使えばよいですか? A. 「n行前まで」「現在の行まで」を1行ずつ数えたいなら ROWS です。「同じ値の行はまとめて扱う」「直近7日間のように値の範囲で区切る」なら RANGE を使います。迷ったときは、フレームを省略せずに明示すると意図が伝わります。

Q. MySQL 5.7でも使えますか? A. MySQLでウィンドウ関数が使えるのは 8.0以降です。5.7ではユーザー変数や自己結合で代用することになるため、バージョンアップを検討する際の判断材料になります。

Q. ウィンドウ関数は遅いですか? A. 並べ替えが必要な分のコストはありますが、同じ結果を自己結合や相関サブクエリで書くより、表を読む回数が少なく済むことが多いです。実行計画で Sort の件数を確認し、必要に応じてインデックスを検討します。

まとめ

  • ウィンドウ関数は、行を減らさずに、グループ内の順位・合計・前後の値を各行に付け足す
  • PARTITION BY で分け、ORDER BY で並べ、フレーム句で範囲を決める
  • 同点の扱いは ROW_NUMBER(別番号)、RANK(飛ばす)、DENSE_RANK(飛ばさない)
  • ORDER BYありの既定フレームは RANGE。1行ずつの累計は ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW を明示
  • 前月比は LAG、パーティション全体の最後は LAST_VALUE + UNBOUNDED FOLLOWING
  • WHEREでは使えない。上位N件はCTEかサブクエリで包んで絞り込む
  • MySQLは 8.0以降で利用可能。PostgreSQL・MySQLに QUALIFY はない

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「SQLウィンドウ関数の使い方|累計・前月比・上位N件を実行結果で解説」

株式会社RJCでは、データの集計や分析をわかりやすいSQLで書く工夫を、プロジェクトの中で仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?