[不懂就问] 两个多对多关联该如何优雅查询?
数据库结构如下:
rosters #排班表
id | name 备注 | date 上班日期 | … |
---|---|---|---|
1 | 加班 | 2020-11-20 | … |
2 | 正常 | 2020-11-19 | … |
N | … | … | … |
shifts #班次表
id | name 上班时间 |
---|---|
1 | 08点-12 点 |
2 | 13点-18 点 |
3 | 19点-23 点 |
4 | 00点-07 点 |
N | … |
staffs #员工表
id | name 姓名 | … |
---|---|---|
1 | 小明 | … |
2 | 小东 | … |
3 | 小红 | … |
4 | 小月 | … |
N | … | … |
roster_shift #排班_班次_中间表
id | roster_id 排班 ID | shift_id班次 ID | 注释 |
---|---|---|---|
1 | 1 | 1 | 班次 1 |
2 | 1 | 2 | 班次 2 |
3 | 1 | 3 | 班次 3 |
4 | 1 | 4 | 班次 4 |
5 | 2 | 1 | 班次 1 |
N | … | … | … |
shift_staff #班次_员工_中间表
id | shfit_id 班次ID | staff_id 员工ID | 注释 |
---|---|---|---|
1 | 1 | 1 | 小明 |
2 | 1 | 2 | 小东 |
3 | 2 | 2 | 小东 |
4 | 3 | 3 | 小红 |
5 | 4 | 4 | 小月 |
6 | 1 | 1 | 小明 |
N | … | … |
结构图
问题回溯
根据上面表格列出的数据,查询关联的班次再查询关联的员工
$rosters = Roster::with('shifts.staffs')->get();
查询结果如下:
Array
(
[0] => Array
(
[id] => 1
[name] => 加班
[date] => 2020-11-20
[created_at] => 2020-11-22T12:34:09.000000Z
[updated_at] => 2020-11-22T12:34:09.000000Z
[shifts] => Array
(
[0] => Array
(
[id] => 1
[name] => 08点-12点
[pivot] => Array
(
[roster_id] => 1
[shift_id] => 1
)
[staffs] => Array
(
[0] => Array
(
[id] => 1
[name] => 小明
[status] => 0
[pivot] => Array
(
[shift_id] => 1
[staff_id] => 1
)
)
[1] => Array
(
[id] => 2
[name] => 小东
[status] => 0
[pivot] => Array
(
[shift_id] => 1
[staff_id] => 2
)
)
)
)
[1] => Array
(
[id] => 2
[name] => 13点-18点
[pivot] => Array
(
[roster_id] => 1
[shift_id] => 2
)
[staffs] => Array
(
[0] => Array
(
[id] => 2
[name] => 小东
[status] => 0
[pivot] => Array
(
[shift_id] => 2
[staff_id] => 2
)
)
)
)
[2] => Array
(
[id] => 3
[name] => 19点-23点
[pivot] => Array
(
[roster_id] => 1
[shift_id] => 3
)
[staffs] => Array
(
[0] => Array
(
[id] => 3
[name] => 小红
[status] => 0
[pivot] => Array
(
[shift_id] => 3
[staff_id] => 3
)
)
)
)
[3] => Array
(
[id] => 4
[name] => 00点-07点
[pivot] => Array
(
[roster_id] => 1
[shift_id] => 4
)
[staffs] => Array
(
[0] => Array
(
[id] => 4
[name] => 小月
[status] => 0
[pivot] => Array
(
[shift_id] => 4
[staff_id] => 4
)
)
)
)
)
)
[1] => Array
(
[id] => 2
[name] => 正常
[date] => 2020-11-20
[created_at] => 2020-11-22T12:34:09.000000Z
[updated_at] => 2020-11-22T12:34:09.000000Z
[shifts] => Array
(
[0] => Array
(
[id] => 1
[name] => 08点-12点
[pivot] => Array
(
[roster_id] => 2
[shift_id] => 1
)
[staffs] => Array
(
[0] => Array
(
[id] => 1
[name] => 小明
[status] => 0
[pivot] => Array
(
[shift_id] => 1
[staff_id] => 1
)
)
[1] => Array
(
[id] => 2
[name] => 小东
[status] => 0
[pivot] => Array
(
[shift_id] => 1
[staff_id] => 2
)
)
)
)
)
)
)
问题总结:
通过数据库的数据对比查询结果可以看出
$rosters[1]
也就是2020-11-19
排班日,这条数据正确结果应该是在2020-11-19 08点-12点
这个班次 只有小明
一个员工才对,但是由于目前的数据表关联关系,导致查出来多了个小东
,小东
实际上是属于第一条的数据,也就是 排班表 ID 为 1 的那条数据。
错误结果如下:
排班日期 | 班次 | 员工 |
---|---|---|
2020-11-20 | 08点-12点 | 小明,小东 |
13点-18点 | 小东 | |
19点-23点 | 小红 | |
00点-07点 | 小月 | |
2020-11-19 | 08点-12点 | 小明,小东 |
期望结果如下:
排班日期 | 班次 | 员工 |
---|---|---|
2020-11-20 | 08点-12点 | 小明,小东 |
13点-18点 | 小动 | |
19点-23点 | 小红 | |
00点-07点 | 小月 | |
2020-11-19 | 08点-12点 | 小明 |
已做尝试
我自己尝试过在
shift_staff
中间表加 1 个roster_id
字段,用来关联,但是这样子的话,所有的CURD
操作每次都要写很多foreach
和条件来查询对应的员工,感觉非常的不优雅,特别是如果不使用DB
只用Eloquent
的方式的话,更加不好弄,当然可能是没经验想不出更好的办法。
寻求解决
上面列举的只是 2 条数据的情况下,如果数据再多一点的会导致
班次和员工
的关联数据全部错误,目前的疑问是不知道如何改进,到底是我们数据表关联的有问题,还是建表就有问题。或是说查询方式不对呢。新手刚接触 laravel不久虚心受教,最好能贴代码参考。
推荐文章: