2017-12-22 12 views
2

나는 캐릭터 (hasMany) 동영상 관계가 있다고 가정 해 봅시다.이 PostgreSQL 쿼리를 단순화하는 방법 (조인 된 테이블로 필터링)

결과를 문자 이름과 영화 제목으로 필터링하고 싶습니다. 그래서 'Sam'과 같은 이름의 모든 캐릭터를 반환하고 싶습니다. 캐릭터는 영화 제목이 'Sam the Movie'와 같은 적어도 하나의 영화에 있어야합니다. 나는 여전히 문자들과 관련된 모든 영화들을 갖고 싶다..

더 좋은 방법이 있는지 궁금합니다. 하나의 쿼리에서 가져올 수 있습니까?

WITH t1 AS 
(SELECT c.id, c.name, array_agg(m.title) AS movie_titles FROM characters c 
LEFT JOIN characters_movies cm ON cm.character_id = c.id 
LEFT JOIN movies m ON m.id = cm.movie_id 
WHERE c.name LIKE '%Sam%' 
GROUP BY c.id) 

SELECT * FROM t1 WHERE exists 
(SELECT * FROM unnest(movie_titles) AS title 
WHERE name LIKE '%Sam the Movie%') 

답변

0

하나의 쿼리에서이 형식은 ddl없이 테스트 할 수 없습니다. 서로 다른 별칭을 사용하여 두 번 영화에 참여한 방법에 유의하십시오. m와 결합하면 제목이 일치하는지 확인합니다. 두 번째는 am이며 모든 타이틀을 얻는 것입니다. 난 꽤 LEFT JOIN을 사용하여 당신이 원하는 결과를 얻는 데 필요하지 않다는 것을 확신한다. 그래서 나는 더 효율적일 경향이있는 보통의 JOIN을 사용했다.

SELECT c.id, c.name, array_agg(am.title) AS movie_titles 
    FROM characters c 
    JOIN characters_movies cm ON cm.character_id = c.id 
    JOIN movies m ON (m.id = cm.movie_id AND m.name LIKE '%Sam the Movie%') 
    JOIN characters_movies acm ON acm.character_id = c.id 
    JOIN movies am ON (am.id = acm.movie_id) 
WHERE c.name LIKE '%Sam%' 
GROUP BY c.id 
+0

이 쿼리는 이전에 문제가되었던 (이전에는 올바른 문자를 가져 왔지만 이름과 일치하지 않는 모든 동영상을 제거하는) 영화를 필터링합니다. 나는 당신의 쿼리를 사용하여 솔루션을 얻을 수 있었다. 'WHERE' 절에'AND'를 추가하고 문자 ID가 같은 쿼리에 있는지 확인했습니다. 그것이 동일한 테이블에서 두 번 선택하고 있기 때문에 그것이 이전보다 좋았는지 확실하지 않습니다. – cdv

+0

@cdv, 필자는'characters_movies'에 두 번 참여해야한다는 것을 간과했으며, 필자는 대답을 업데이트했습니다. – Eelke

+0

현재 작동 중입니다. 접합점 테이블에 두 번 결합 할 생각은 없었을 것입니다. 감사! – cdv