생각을 개발하자, 박진형

[rails] 레일즈 모델 - 쿼리메서드 본문

Likelion/rails

[rails] 레일즈 모델 - 쿼리메서드

imjinbro imjinbro 2017.02.21 01:07

[모델 활용 기본개념]
레일즈의 기본(루비의 기본) : 객체.메서드, 모든 흐름은 객체가 어떤 메서드를 사용하는가에 초점이 맞춰져있음


[모델 객체+메서드로 db 테이블 접근하기 - 쿼리메서드, 쉽고 빠르게 쿼리문을 날리기] 
1) 메서드 사용 명령 즉시 데이터베이스에 접근하여 알맞는 레코드를 찾아오는 메서드
2) 메서드 사용 명령 시점에 데이터를 뽑지않고, 조건에 조건을 더해 최종적으로 데이터가 필요할 때 뽑아오는 쿼리문을 날림
3) 데이터 수정 쿼리메서드
4) 데이터 삭제 쿼리메서드


[선택 쿼리메서드 1번째 방법]
쿼리문 : SELECT에 해당함 : SELECT "테이블명"  .칼럼명( *을 씀으로서 모든 칼럼을 선택할 수 있음) FROM "모델객체명"

1) find(key) : 레코드 idx 값으로 데이터찾기, key는 배열 형태도 가능(여러개 찾기 가능) - 쿼리문에서 WHERE의 기능을 함
2) find_by(key: "value") : key에는 칼럼, value에는 칼럼의 값을 적는다. 
해당 조건에 맞는 데이터 1개(첫번째 검색되는 것) 추출해옴, key/value로 이뤄진 조건은 여러개 상관없음(논리연산을 함)
3) first, last : 첫번째, 마지막 데이터를 뽑아오는 메서드
4) pluck(:key) : key에는 칼럼명을 넣고 특정 칼럼값들을 모두 빼와서 배열형태로 만들어줌, key로 여러개 칼럼 사용 가능


[선택 쿼리메서드 2번째 방법]
쿼리문 : SELECT에 해당함 : SELECT "테이블명"  .칼럼명( *을 씀으로서 모든 칼럼을 선택할 수 있음) FROM "모델객체명"
(특징)  
- 체이닝이 가능함(find처럼 딱 이것만 찾아라가 아니라 여러 조건을 한번에 걸 수 있음)
- 쿼리메서드를 날린 후 터미널을 살펴보면 find와 다른 결과가 나옴(같은 역할인데도 불구) ActiveRecord 형태(배열형)리턴함   

1) where(key: "value") : key(칼럼명)/value(값)로 찾는 조건을 완성함, value에 배열형태([1,2,3]), 범위형태(a..b) 가능함
2) where('key 비교연산자 value') : 칼럼(key)이 가지는 값이 비교연산자에 따라 찾는 값이 달라지도록 설정할 수 있음
3) 플레이스홀더 :  value에 특정 값을 미리 지정해주지 않고, 값을 받아와(파라미터) 대입하는 형태로 쿼리메서드를 짜는 것
사용방법1 : where('key1 = ? AND key2 >= ?', params[:key1], params[:key2]) - 받은 데이터를 대입시켜, 논리연산자로 뽑음
사용방법2 : where('key1 = :key1_name', key1_name: params[:key1])  - 받은 데이터를 대입시키는 형태가 1번과 다름
4) not(key: "value") : where과 같이 쓰는 조건식으로 .where.not(포함시키지않을칼럼명: "포함시키지않을값")
5) order(key: :정렬형식) : 정렬하는 메서드로 정렬형식으로는 asc(오름차순), desc(내림차순)이 있다. key에는 db table 칼럼명이 들어간다.
    order(key1: :정렬형식, key2: :정렬형식) : key와 정렬형식을 여러가지로 줘서 여러 조건을 통해 정렬하는 것도 된다.
    order(:key) : 정렬형식(asc, desc)을 생략하고 :key 만 입력했다면 오름차순으로 정렬을 하라는 것.
    order(:key1).order(:key2) : 오름차순으로 정렬하고 두번에 걸쳐 정렬을 하겠다는 것 
6) reorder(:key) 혹은 reorder(key: :정렬형식) : 앞의 정렬은 모두 없었던 것으로 하고 재정렬 하겠다는 것
    reorder(nil) : 정렬했던 것을 모두 없애버림
7) select(:column_name) : 하나의 칼럼에 해당되는 모든 값들을 추출하는 것,  ,(콤마)로 여러 칼럼을 설정, 뽑아낼 수 있음
8) distinct : 데이터를 찾는 메서드들과 같이 쓰는 메서드로 중복되는 값들을 제거하고 출력할 때 사용함
9) limit(숫자) : 찾을 데이터 숫자를 제한 거는 것, 숫자만큼만 찾아옴
10) offset(숫자) : 뽑아올 데이터 시작지점을 숫자+1부터 지정하는 메서드
11) group(:key) : 테이블의 두개 이상의 칼럼을 하나의 칼럼(key로 설정된)으로 묶어서 조회하겠다는 것
=> p = Percentage.select('user_name, correct').group(:user_name)
=> b = Book.select('publish, AVG(price) AS avg_price').group(:publish) - 책 정보 테이블에서 출판사와 가격 칼럼을 출판사 하나로 묶는데(조회할 때 출판사로 조회하면 가격까지) 그냥 가격이 아니라 평균값이 계산된 가격(AS 별명 별명을 지어줘야함)
=> select에서 데이터 추출 관련 메서드 SUM(파라미터), AVG(파라미터), COUNT(파라미터)
12) having : group을 통해서 두개 이상의 칼럼을 하나의 칼럼으로 합치고 난 결과에 추가 조건을 적용시켜 특정 데이터를 뽑아올 때 사용함
=> b = Book.select('publish, AVG(price) AS avg_price).group(:publish).having('AVG(price) >= ?', 25000)
13) unscope(:쿼리메서드명1, :쿼리메서드명2) - 앞에서 배웠던 where나 order, reorder, limit등 쿼리메서드를 없애는 메서드
=> 주의해야할점은 unscope가 적용되기 이전에 선언된 쿼리메서드에만 unscope가 적용됨
=> Book.where(category: "문학").order(:price).select(:title, :price).unscope(select: :title) - select 메서드에서 title 데이터 선택 조건만 날아감
14) none -아무런 데이터도 뽑히지 않는 메서드, 필요한 이유는 어떤 값을 받아서(액션메서드의 파라미터) 조건문으로 처리할 때 아무런 값이 오지않거나 어디에도 해당되지 않는다면 빈값에 대한 처리를 해야하는데 따로 nil에 대한 예외처리를 해야한다는 뜻이다. 굳이 예외처리(nil에 대한 if문 처리)를 하지않고 none을 뽑아줌(count를 돌려보면 0으로 처리됨)으로서 아무런 값도 출력되지않게하고, 예외처리도 한번에 하도록 할 수 있음
15) group( :그룹의헤드가되는칼럼명).having('조건문 비교연산자 ?', ?에 들어갈 조건값) - 두개 이상의 칼럼을 하나의 칼럼으로 묶어서 하나의 칼럼의 조건에 맞는 어떤 특정 칼럼을 빼오기위해서 사용, having은 단독으로 사용 불가능
 => 사용예시 : Book.select(:title, :price).group(:title).having('price > ?', 10000) - 타이틀과 가격을 하나로 묶되 가격이 10000원 이상 넘어가는 데이터만 가져옴, 그러고 난 후 title을 빼내겠지? 두개를 하나처럼 사용함
16) count - 앞서 알아본 쿼리메서드 뒤에 count를 붙이면 추출된 데이터가 몇개인지 알 수 있는 메서드
17) average(:평균값을추출할기준칼럼명) - 선택한 칼럼(where 등 테이블 데이터 선택 메서드를 통해서)에 대한, 혹은 모든 데이터에 대한 평균값을 추출해내는 칼럼명 + 값이 클 경우(범위가 큰) integer로 데이터형을 변경해야만 정수를 볼 수 있음
18) maximum(:최대값을추출할기준칼럼명) - 18번과 동일한 사용방법이나 최대값을 추출해내는 쿼리메서드
19) minimum(:최소값을추출할기준칼럼명) - 18, 19번과 동일한 사용방법이나 최소값을 추출해내는 쿼리메서드
20) sum(:합계를낼칼럼명) - 18, 19, 20번과 동일한 사용방법이나 선택한 db 테이블 칼럼의 합계를 낼 칼럼명만 추출하여 합계를 내는 메서드, 정수형/소수형으로만 표현됨
21) find_by_sql(['쿼리문']) - 복잡한 쿼리문일 때 쿼리메서드 대신 직접 쿼리문을 작성할 수 있는 메서드
     

[수정 쿼리메서드]
쿼리문 : UPDATE에 해당함 : UPDATE "모델명" SET 업데이트쿼리문 WHERE "모델명".선택쿼리문

1) update_all(수정할칼럼: 수정할value 혹은 쿼리문 - 어떻게 값을 업데이트 시킬 것인지) - SELECT 쿼리메서드와 함께 사용할 것,  선택한 칼럼에 대해 모두 변경을 하는 메서드(여러개 레코드 수정), 리턴되는 값은 몇개가 바뀌었는지 알려줌
=> Book.where(category: "연애").update_all("price = price * 1.5")
2) update(수정할칼럼: 수정할value) - 하나의 레코드에 대한 칼럼값 수정을 진행할 때 사용하는 메서드, SELECT 쿼리메서드와 함께 사용함


[삭제 쿼리메서드]
쿼리문 : DELETE에 해당함 : DELETE FROM "모델명" WHERE "모델명".선택쿼리문

1) destory(db테이블레코드id값) - db 테이블 레코드 중 하나의 레코드를 삭제할 때 사용함, 액티브 레코드 기능을 사용할 때 delete가 아닌 destroy 메서드를 사용함
2) delete(db테이블레코드id값) - db 테이블 레코드 중 하나의 레코드를 삭제할 때 사용함, 1번과 다른 점은 쿼리메서드를 날리고 터미널의 쿼리문을 보면 알 수 있음. 1번은 SELECT -> DELETE로 진행하지만 2번은 곧바로 DELETE
3) destroy_all(cond) - db 테이블 레코드 중 cond에 맞는 레코드를 삭제할 때 사용함, 리턴되는 값은 삭제된 개수를 리턴함, cond란? where구문에 넣는 조건식과 같은 구조 (["조건식", 매개변수값])이다, 조건문인 것

=> Book.destroy_all(['publish != ?', '제이펍']) - 출판사가 제이펍이 아닐 경우 삭제를 함