개발 꿀팁/PHP

laravel query builder 사용 하위 조회

Jammie 2022. 8. 4. 10:59
반응형

개요:
프로젝트에는 복잡한 SQL 대역 서브쿼리가 많이 사용되는데, Laravel의 쿼리 빌더는 직접 서브쿼리로 변환하는 방법을 제공하지 않거나, 방법을 제공하지만 구체적인 예를 제시하지 못해 초보자에게는 매우 불친절합니다. 이 장에서는 Laravel이 서브쿼리가 있는 SQL을 어떻게 구성하는지 주로 이야기합니다.

준비:
우선, 라라벨은 일반적으로 서브쿼리의 두 가지 방식을 구현하고 있습니다.

1, toSql()+getQuery()+raw() 방법:
1.tosql() 메서드는 binding 매개 변수가 없는 SQL, 즉 물음표가 붙은 SQL을 얻기 위한 역할을 한다.

select * from `rooms` where `rooms`.`project_id` = ?

1.getQuery() 방법은 binding 파라미터를 얻고 tosql() 대신 SQL 물음표를 획득하여 완전한 SQL을 얻기 위한 것입니다

select * from `rooms` where `rooms`.`project_id` = 3

1.raw( )는 Laravel의 쿼리 빌더에 SQL을 직접 끼우는 역할을 합니다

  `$sql = 'select * from `rooms` where `rooms`.`project_id` = 3';
  $resultSql = DB::table('DB::raw($sql as room')->toSql();`

그러면 SQL을 획득할 수 있습니다

select * from (select * from `rooms` where `rooms`.`project_id` = 3) as room

주의: SQL을 직접 사용하는 것은 raw()뿐만 아니라 whereRaw()

2, 쿼리 빌더를 사용하여 일부 자체적인 폐쇄형 패킷

예를 들어:
User::whereIn('id', function($query){ 
    $query->select('user_id') 
    ->from('admin_user') 
    ->whereIn('type', ['1', '2']); 
})->get();

얻을 수 있는 SQL:

select * from `user` where `id` in (select `user_id` from `admin_user` where `type` in (1, 2));

이와 같은 폐쇄형 서브쿼리 구현에는 whereExists, where 등이 있다.

예:
PHP 코드:

    $ipCountObject = new \Model\BlacklistIpCountDate();
    $ipCountObj = $ipCountObject->selectRaw("sum(attack_count) AS attack_times, ip")->where('attack_count', '>', '0')->whereBetween('data', ['2017-10-10', '2017-10-11'])->groupBy('ip');
    $totalObj = DB::table( DB::raw("({$ipCountObj->toSql()}) as sub, blacklist_attack_ip"))->mergeBindings($ipCountObj->getQuery())->select('attack_ip', 'country', 'province', 'city', 'line', 'info_update_time AS attack_time', 'attack_times'); //toSql获得的sql有?,需要填入变量
    $totalObj = $totalObj->where('blacklist_attack_ip.attack_ip', '=', 'sub.ip')->get();

SQL 획득 가능:

SELECT
    `attack_ip`,
    `country`,
    `province`,
    `city`,
    `line`,
    `info_update_time` AS `attack_time`,
    `attack_times` 
FROM
    ( SELECT sum( attack_count ) AS attack_times, ip FROM `blacklist_ip_count_date` WHERE `attack_count` > 0 AND `date` BETWEEN '2017-10-10' AND '2017-10-11' GROUP BY `ip` ) AS sub,
    blacklist_attack_ip 
WHERE
    `blacklist_attack_ip`.`attack_ip` = `sub`.`ip`

요약:
이 두 가지 방법을 모두 활용해야 한다. 첫 번째 방법은 기본적으로 하위 쿼리에 공통적으로 적용되며, 두 번째 방법은 where와 관련된 위치에만 적용됩니다.물론 개인적인 조언은 획일적이다. 만약 당신이 프로젝트에 첫 번째를 사용한다면, 당신은 where의 하위 조회도 첫 번째의 편리함을 고수해야 한다.이 외에도 Laravel 쿼리 빌더는 join, lefeJoin, rightJoin 등 다른 클로즈드 패킷을 제공하지만, 이러한 클로즈드 패킷은 개별 테스트 결과 하위 쿼리를 구현하지 못합니다.

 

반응형