2012-12-03 4 views
3

매우 간단,이포스트 그레스 레일에서 CONCAT 필드와 ILIKE을 선택

SELECT (artist_name || ' ' || name) as full_name FROM "songs" WHERE "songs"."working" = 't' AND (full_name ILIKE('%Jack Beats%')) AND (full_name ILIKE('%Epidemic%')) AND (full_name ILIKE('%Dillon Francis%')) ORDER BY songs.published_at asc LIMIT 1 

을하려고하지만 더와 역 앞에 테이블 이름을 추가하려고했습니다 나는

ActiveRecord::StatementInvalid: PG::Error: ERROR: column "full_name" does not exist 

를 얻을 수 효과.

+0

where 절에서 직접 열에 명명 된 별칭을 사용할 수 없기 때문에. 하위 쿼리에서 가져와야합니다. – Subodh

답변

2

where 절에서 열 별칭을 참조 할 수 없습니다. 이 쿼리를 작성하는 올바른 방법은 다음과 같습니다

SELECT 
    (artist_name || ' ' || name) AS full_name 
FROM "songs" 
WHERE "songs"."working" = 't' 
AND ((artist_name || ' ' || name) ILIKE('%Jack Beats%')) 
AND ((artist_name || ' ' || name) ILIKE('%Epidemic%')) 
AND ((artist_name || ' ' || name) ILIKE('%Dillon Francis%')) 
ORDER BY songs.published_at ASC 
limit 1 
; 

sub_stantial의 접근 방식은 더 같을 것이다 :

그들은 모두가해야 할이 두 쿼리의
select full_name 
from (
    SELECT 
     (artist_name || ' ' || name) AS full_name 
    FROM "songs" 
    WHERE "songs"."working" = 't' 
    ORDER BY songs.published_at ASC 
) 
WHERE (full_name ILIKE('%Jack Beats%')) 
AND (full_name ILIKE('%Epidemic%')) 
AND (full_name ILIKE('%Dillon Francis%')) 
LIMIT 1 
; 

성능은 동일 (꽤 쓰레기)에 관한 것입니다 전체 테이블을 스캔하여 full_name 열을 작성한 다음 결과를 정렬하십시오. 이러한 쿼리의 속도를 높이려면 "작동 중"에 인덱스를 추가 할 수 있습니다. sub_stantial이 코멘트에 언급 된 바와 같이

가 여기에 sql fiddle in postgresql

7

, 당신은 당신의 WHERE 절에 SELECT에서 별칭을 참조 할 수 없습니다. dwurf가 제안한 것처럼 파생 테이블을 사용할 수 있지만 레일스의 파생 테이블은 약간 지저분합니다. 당신은 내부에 연결을 확장 할 수 귀하의 WHERE 대신 :

Song.where(:working => true) 
    .where("artist_name || ' ' || name ILIKE ?", '%Jack Beats%') 
    .where("artist_name || ' ' || name ILIKE ?", '%Epidemic%') 
    .where("artist_name || ' ' || name ILIKE ?", '%Dillon Francis%') 
    .order('songs.published_at asc') 
    .limit(1) 

그리고 당신은 많은 이런 종류의 일을하는 경우, 명명 된 범위가 유용 할 수 있습니다 : 다음

class Song < ActiveRecord::Base 
    #... 
    def self.full_name_like(name) 
     where("artist_name || ' ' || name ILIKE ?", "%#{name}%") 
    end 
end 

과 :

Song.where(:working => true) 
    .full_name_like('Jack Beats') 
    .full_name_like('Epidemic') 
    .full_name_like('Dillon Francis') 
    .order('songs.published_at asc') 
    .limit(1) 

응용 프로그램이 이와 같이 많은 ILIKE 검색을 수행하는 경우 전체 텍스트 검색 시스템을 살펴볼 수 있습니다. LIKE 쿼리로 인해 테이블 ​​스캔 및 테이블 스캔이 슬픔으로 이어집니다.