ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [CI] active record로 subquery 사용
    PHP 2020. 8. 12. 10:29

    쿼리문을 짤 때, 서브쿼리를 생각보다 많이 사용하게 된다.

    조인을 해서 Full table scan을 피하려면 그래도 서브쿼리가 속도면에서도 더 좋은 것 같다.

    이 부분에 대한 고민은 좀 더 스터디가 필요하다.

     

     

    그렇게 서브쿼리로 쿼리문을 짜다보니 

    $this->db->select("*");
    $this->db->from($this->b_a_db.".bio_question ques");
    $this->db->where('ques.paper_id','(select paper_id from bio_admin.bio_reservation where rs_key = (select rs_key from bio.bio_tester where tester_id='.$this->session->userdata('tester_id').'))',false);
    $this->db->where('ques.q_num',$q_real_num);
    $query = $this->db->get()->row_array();

    가로스크롤이 엄청나게 생겨나는 이런식의  구문이 탄생하게 되었다.

    코드가 직관적이지도 않고, 뭔가 수정하고 싶은 욕구가 계속해서 생겨나는 중..

     

     

    검색을 해보니 get_compiled_select() 로 서브쿼리를 깔끔하게 넣어주는 active record 문법이 있었다.

    $superSubQuery = $this->db->select('rs_key')
                              ->from($this->b_db.'.bio_tester')
                              ->where('tester_id', $this->session->userdata('tester_id'))
                              ->get_compiled_select();
    
    
    $subQuery = $this->db->select('paper_id')
                         ->from($this->b_a_db.'.bio_reservation')
                         ->where('rs_key IN ('.$superSubQuery.')', NULL, FALSE)
                         ->get_compiled_select();
    
    
    $query = $this->db->select("*")
                      ->from($this->b_a_db.".bio_question q")
                      ->where('q.paper_id IN ('.$subQuery.')', NULL, FALSE)
                      ->where('q.q_num', $q_real_num)
                      ->get()
                      ->row_array();

    물론 라인 수는 더 길어졌지만, 좀 더 직관적인 코드가 되었다.

    클린코드에서 코드를 소설읽듯이 읽히도록 구성하라는 메세지가 자꾸만 떠올라서 나는 요즘 코드가 길어져도

    내가 아닌 내 코드를 볼 다른 사용자들을 위해 코드를 구성하려고 한다.

     


    $this->db->get_compiled_select()

    셀렉트 쿼리를 $this->db->get()와 같이 컴파일하지만, 쿼리를 실행하지는 않습니다.
    이 함수는 단지 SQL 쿼리를 문자열로 반환합니다.
    $sql = $this->db->get_compiled_select('mytable');
    echo $sql;
    
    // Prints string: SELECT * FROM mytable
    두 번째 파라미터는 쿼리 빌더를 재설정할지 결정합니다. (기본적으로 $this->db->get()를 사용하는 것처럼 재설정됩니다):
    echo $this->db->limit(10,20)->get_compiled_select('mytable', FALSE);
    
    // Prints string: SELECT * FROM mytable LIMIT 20, 10
    // (in MySQL. Other databases have slightly different syntax)
    
    echo $this->db->select('title, content, date')->get_compiled_select();
    
    // Prints string: SELECT title, content, date FROM mytable LIMIT 20, 10
    위의 예제에서 알 수 있는 중요한 것은,
    두 번째 쿼리는 $this->db->from()를 사용하지 않았고, 테이블명을 첫 번째 파라미터로 전달하지 않았다는 것입니다.
    이 결과에 대한 이유는 쿼리가 값을 초기화하는 $this->db->get()를 사용하지 않았기 때문입니다.

     

     

    [참조]

    http://www.ciboard.co.kr/user_guide/kr/database/query_builder.html

     

    Query Builder Class ‐ 코드이그나이터 3.0 한글매뉴얼

    TRUE on success, FALSE on failure

    www.ciboard.co.kr

     

    'PHP' 카테고리의 다른 글

    Active Record에서 insert() 반환값  (0) 2020.07.28

    댓글

Designed by Tistory.