doubi7496 2019-04-24 18:02 采纳率: 0%
浏览 161
已采纳

Laravel中三个表的复杂查询

I have a problem what I can’t solve with Laravel. I have three table:

Users, Properties, Offers

Users haveMany Properties and Offers Properties and Offers belongsTo a User

Properties table:
id
user_id
contract_start_date
other_date
…
created_at
updated_at

Offers table:
id
user_id
…
created_at
updated_at

I would like give a table that is like this (I use two date filter: startDate and endDate):

Users name || Properties count (They are filtered by contract_start_date)  || Properties count (They are filtered by other_date) || Offers count
———

user1 || 5 || 2 || 12
user2 || 0 || 1 || 0
user3 || 0 || 0 || 0
…

I try with union, leftJoin, etc but I can’t solve this… Thanks, if you can help

  • 写回答

1条回答 默认 最新

  • dongshi1102 2019-04-24 19:37
    关注

    Quick and Dirty

    First, get your users eager loading their properties' dates and all the offers.

    $users = Users::with([
        'property'=>function($query){
            $query->select('contract_startdate','otherdate');
        },
        'offer'=>function($query){
            $query->select('id');
        },
    );
    

    Assuming you've properly set the $dates array in your model to include your contract_startdate and other_date. We can use carbon to filter the collection to get the properties we're interested in counting. In your view, you can:

    <table>
      <thead>
         <tr>
           <th>User</th>
           <th>Property (start date)</th>
           <th>Property (other date)</th>
           <th>Offers</th>
         </tr>
       </thead>
       <tbody>          
       @foreach($users as $user)
           <tr>
               <td>{{$user->name}}</td>
               <td>{{$user->properties
                   ->filter(function($item) use ($filter_start,$filter_end){
                       return $item->contract_startdate->between($filter_start,$filter_end);
                   })->count() }}</td>
               <td>{{$user->properties
                   ->filter(function($item) use ($filter_start,$filter_end){
                       return return $item->other_date->between($filter_start,$filter_end);
                   })->count() }}</td>
               <td>{{$user->offers->count()}}</td>
           </tr>
       @endforeach
       </tbody>
    </table>
    

    Cleaning that up

    You should likely refactor the filter out of the view for cleanness, but doing so will add another loop over collection. But you might be able to remove a loop by doing something like this in your controller.

    $users = Users::with([
        'property'=>function($query){
            $query->select('contract_startdate','otherdate');
        },
        'offer'=>function($query){
            $query->select('id');
        },
    );
    
    $byContractDate = collect();
    $byOtherDate = collect();
    
    foreach($users as $user){
        foreach($properties as $property){
            $contractCounter = 0;
            $otherCounter = 0;
            if($propery->contract_startdate->between($filter_start,$filter_end){
                 $contractCounter++;
            }
            if($propery->contract_startdate->between($filter_start,$filter_end){
                 $otherCounter++;
            }
        }
        $byContractDate->put($user->id,$contractCounter);
        $byOther->put($user->id,$otherCounter);
    }
    

    And in your view:

    <table>
      <thead>
         <tr>
           <th>User</th>
           <th>Property (start date)</th>
           <th>Property (other date)</th>
           <th>Offers</th>
         </tr>
       </thead>
       <tbody>          
       @foreach($users as $user)
           <tr>
               <td>{{$user->name}}</td>
               <td>{{$byContract->get($user->id)}}</td>
               <td>{{$byOther->get($user->id)}}</td>
               <td>{{$user->offers->count()}}</td>
           </tr>
       @endforeach
       </tbody>
    </table>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮