ちょうどやりたいことができそうだったので、 MySQL8.0 で新しく追加された再帰クエリを使ってみました。なお、単独インストールした Eloquent での使用を想定しているので、リレーションの機能をそのまま使うのは難しそうなケースでした。
経緯
内容としてはありがちな部署マスタのようなもので、親子関係まで見たいと考えたためでした。
id | parent | name |
---|---|---|
1 | 0 | 営業部 |
2 | 1 | 営業1課 |
3 | 1 | 営業2課 |
4 | 0 | システム部 |
5 | 4 | 開発課 |
6 | 4 | 運用保守課 |
7 | 5 | フロントエンドグループ |
8 | 5 | バックエンドグループ |
イメージとしてはこんなイメージのテーブルがあったとして、例えば「システム部」と指定した場合、「開発課」「運用保守課」「フロントエンドグループ」「バックエンドグループ」のIDを子部署として参照したい、というようなケースです。
コード
$hogeObjectsArray = $this->dbConnect->connection('hogera')
->select("
WITH recursive child(
depth,
id,
parent,
name
) AS (
SELECT 0,
id,
parent,
name
FROM hoge
WHERE id = {$foo}
UNION ALL
SELECT child.depth + 1,
hoge.id,
hoge.parent,
hoge.name
FROM hoge, child
WHERE hoge.parent = child.id
)
SELECT depth,
id,
parent,
name
FROM child
ORDER BY
depth
");
最終的には上述の形で取得できました。
->table($this->table)
等でテーブルを指定せず、いきなり ->select()
しているのがミソです。
参考
with recursive
単独の Eloquent 内で with recursive を使用したい
- 100行ぐらいのSQLをLaravelのEloquent\/Query Builderで頑張る – Qiita
- Laravel5で生のSQLを実行する方法
- MySQL — サブクエリに AS を付けないとエラーを起こす | Every derived table must have its own alias – Qiita
メソッド確認
- Illuminate\Database\Capsule\Manager | Laravel API
- query(): Illuminate\Database\Connection | Laravel API
- Builder: Illuminate\Database\Query\Builder | Laravel API
- selectRaw(): Illuminate\Database\Query\Builder | Laravel API
- select(): Illuminate\Database\Query\Builder | Laravel API
- raw(): Illuminate\Database\Connection | Laravel API
unionAll
- unionAll(): Illuminate\Database\Query\Builder | Laravel API
- MySQL の UNION \/ UNION ALL – MySQL の基礎 – MySQL 入門