2016-08-20 6 views
1

내 postgresql db에서 복잡한 구조의 비정규 화 된보기를 만들고 싶습니다. 나는 주체가 games이고, 약간의 일대 다 릴레이션 (예 : tags (두 가지 유형) 및 files)이 있습니다. 문제는 서브 쿼리 안에 distinct 절에 관계없이 배열에 중복 ID가있는 항목을 포함한다는 것입니다. 그런 다음 쿼리 결과에 내가 배열 [100, 100, 100, 100]를 볼 수 있습니다 복잡한 배열의 중복 배열

select 
    array_to_json(array_remove(array_agg((
    select distinct t.id where t.type = 1 
)), null))::jsonb as genre_ids 
from games g 
left outer join game_tags gt on gt.game_id = g.id -- one-to-many 
left outer join tags t on gt.tag_id = t.id 
left outer join game_files gf on gf.game_id = g.id -- one-to-many as well 
left outer join files f on gf.file_id = f.id 
left outer join ratings r on r.game_id = g.id 
group by g.id; 

이의 내가 id=1와 함께 게임을 가정 해 봅시다과 관계

# game_tags (game_id, tag_id) 
1, 100 

# game_files (game_id, file_id) 
1, 1000 
1, 1001 
1, 1002 
1, 1003 

: 나는 관련 부분에 쿼리를 좁힐 수 있습니다. 태그 양이 1보다 큰 동일한 상황. 나는 틀린 모으기 단면도 때문에 또는 틀린 그룹 때문에 이것을 모른다. 나는 distinct 키워드가 속임수를 쓸 것이라고 기대했으나 그렇지 않습니다. 물론 프론트 엔드로 보내기 전에 항목을 필터링 할 수 있지만 이것이 잘못된 방법이라고 생각합니다.

9.5 페이지에 붙어 있습니다.

+0

아니요,'tags'는 태그 목록 일 뿐이며'game_tags'는 관계입니다. 방금 쿼리를 간소화 했으므로 파일도 필요합니다. 집계도 꽤 비슷합니다. select distinct clause에서 type = 1의 태그 만 필터링하고 type은'tags' 테이블에 저장해야합니다. 아마도 나는 개념적으로 잘못된 것을하고있을 것입니다. – Tommi

답변

1

문제는 게임 태그에 한 번, 파일에 한 번 다른 그룹으로 그룹화해야한다는 것입니다. 행 소스로 서브 u 리로이를 해결할 수 있습니다. 그룹화는 하위 쿼리에서 발생하므로 서로 영향을주지 않습니다.

select g.*, t.genre_ids, f.file_ids 
from games g 
left join (
    select gt.game_id, jsonb_agg(t.id) as genre_ids 
    from game_tags gt 
    join tags t on gt.tag_id = t.id 
    where t."type" = 1 
    group by gt.game_id) t on t.game_id = g.id 
left join (
    select game_id, jsonb_agg(file_id) as file_ids 
    from game_files 
    group by game_id) f on f.game_id = g.id 
left join ratings r on r.game_id = g.id -- not used 
; 
+0

고맙습니다. 내가 예상했던대로 정확하게 작동합니다. 너무 나쁘게 나는 그것을 스스로 깨닫지 못했습니다. – Tommi

+0

그래서 우리는 서로에게서 배울 수 있습니다. 나는 주변을 둘러 봄으로써 훌륭한 코딩 기법을 배웠다. 미래의 코딩과 함께 행운을 빈다. – Patrick