laravel 模型 unionALL数据错乱问题

说明:在laravel中需要合并的两个模型各自关联的模型不同数据无法加载以及可以加载但是出现数据错乱的问题如何解决?

1.前一个模型和后一个模型有相同的关联模型,但是前一个模型的关联模型的数据会覆盖到后一个模型的关联模型中

解决方法尝试

1.先合并模型再加载关联模型直接使用失败,需要自己对合并后的数据进行遍历处理

2.对模型进行按需加载同样会被覆盖

3.使用collection 并且保留分页功能

<?php
    namespace App\Http\Controllers;
    use Illuminate\Http\Request;
    use App\Models\                        {Sell,Sre,Borrow,Lend,Record,User,SellInfo,SreInfo,BorrowInfo,LendInfo,Relation,Cost,Borr        owRestore};
    use Illuminate\Support\Facades\DB;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\Storage;
    use Illuminate\Support\Facades\Validator;
    use App\Notifications\Message;
    use App\Http\Controllers\Summary;
    use Illuminate\Support\Collection;
    use Illuminate\Pagination\LengthAwarePaginator;
    use App\Http\Validate\{BorrowAndBorrowRestore as Validate /*as BorrowValidate,         BorrowInfo as BorrowInfoValidate,Cost as CostValidate,Lend as LendValidate,LendInfo as     LendInfoValidate,Sell as SellValidate,SellInfo as SellInfoValidate,Sre as     SreValidate,SreInfo as SreInfoValidate,Order as OrderValidate*/};
    class BorrowAndBorrowRestore extends Controller{
    
        //数据记录
        public function record(Request $request,Validate $validate,Query $query){
            /****************************************************************************************    /
            //对于不同关联的模型,在合并查询结果之后再次使用 `with` 方法加载额外的关联模型数据可能会导致数据错乱的情况。这是因为在使用 `with` 方法加载关联数据时,模型会尝试匹配当前模型的关联关系,而合并后的模型可能并不是符合原有关联关系的结构,导致加载的关联数据不正确。

            //为了解决这个问题,可以考虑使用手动加载关联数据的方式来避免数据错乱的情况。具体实现如下:
        
            // ```php
            // use App\Models\A;
            // use App\Models\B;
            // use App\Models\C;
            // use App\Models\D;
        
            $input=$request->input();
            // 加载 A 模型的数据和关联模型 C 的数据
            $modelsA =     Borrow::with(['userData','recordData','customerData','borrowInfoData','borrowRestoreData'])->select('id','number','state','time','amount','total','user','examine','type','data','customer','borrow_nums','borrow_restore_nums',DB::raw("-1 as nums"))->orderBy('state','asc')->orderBy('id','desc')->paginate($input['size']);
            // 加载 B 模型的数据和关联模型 D 的数据
            $modelsB =     BorrowRestore::with(['userData','recordData','customerData','borrowInfoData','borrowRestoreInfoData','iceData'])->select('id','number','state','time','amount','total','user','examine','type','data','customer',DB::raw("-1 as borrow_nums"),DB::raw("-1 as borrow_restore_nums"),'nums')->orderBy('state','asc')->orderBy('id','desc')->paginate($input['size']);
        
            // 手动加载关联模型数据
            $mergedModels = $modelsA->merge($modelsB);
            // dd($mergedModels);
            $mergedModelsWithRelations = $mergedModels->map(function ($mergedModel) {
                if ($mergedModel instanceof Borrow) {
                    $mergedModel->with(['borrowInfoData','borrowRestoreData']);
                } elseif ($mergedModel instanceof BorrowRestore) {
                    $mergedModel->with('borrowInfoData','borrowRestoreInfoData','iceData');
                }
                return $mergedModel;
            });
            // dd($mergedModelsWithRelations);
            Collection::macro('paginate', function ($perPage, $page = 1, $options = []) {
                $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
                $results = $this->slice(($page - 1) * $perPage, $perPage + 1);
                return new LengthAwarePaginator($results, $this->count(), $perPage,     $page, $options);
            });
            $paginatedCollection = $mergedModelsWithRelations->paginate($input['size']);
            return $paginatedCollection;
    }
}

### SQL查询合并中的数据丢失解决方案 当使用 `UNION ALL` 操作符时,如果遇到数据丢失或结果不完整的情况,通常是因为两个表之间的连接条件设置不当或是某些记录未能满足预期的匹配逻辑。为了确保所有期望的数据都能被正确返回,可以考虑以下几个方面: #### 1. 使用外连接替代内连接 在外键关联的情况下,应优先选用左/右外部联接而非内部联接来防止因缺少对应关系而导致的部分行遗漏。 对于给定的例子,在处理来自不同源的学生和个人信息时,建议采用左侧外部联接(LEFT JOIN),这能保证即使右侧表中不存在相匹配项也能保留左侧表里的全部条目[^1]: ```sql SELECT id, fullname, birth_city FROM person p LEFT JOIN student s ON p.id = s.person_id; ``` #### 2. 明确指定列名并保持一致 在执行联合操作前,需确认参与运算各子句所选取字段名称相同且顺序统一;否则可能会造成意外的结果集缩减。具体来说就是指明要提取哪些特定属性而不是依赖默认行为。 例如下面这段SQL语句展示了如何通过显式声明所需展示的列来避免潜在冲突: ```sql (SELECT id AS 'ID', fullname AS 'Name' FROM tableA) UNION ALL (SELECT id AS 'ID', name AS 'Name' FROM tableB); ``` #### 3. 调整过滤条件的位置 有时WHERE子句放置位置的不同也会影响最终输出效果。为了避免不必要的筛选影响到整个组合后的集合,请尝试将限定范围仅应用于单个部分而非整体结构之上。 比如这里提供了一种方法是在各自独立的选择范围内应用约束条件从而不影响其他组件的内容获取: ```sql (SELECT * FROM A WHERE condition_A) UNION ALL (SELECT * FROM B WHERE condition_B); ``` 以上措施有助于改善由`UNION ALL`引起的数据完整性问题,并提高查询效率和准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值