Django Annotate와 Union 사용 시 발생하는 문제

Ashe·2020년 3월 11일
0

장고에서 Annotate 와 기존 필드를 Union 하려면 좀 이상하게 작성해야한다.

결론적인 문제점은 Annotate 된 필드는 쿼리의 하위에 작성된다. Values 에 쓰인 순서대로 나왔으면 좋겠지만 그렇지 못한다.

동작하지만 원하는 결과가 나오지 않는 코드

    가맹점쿼리 = 가맹점.objects.annotate(
    	address=F('addr'),
    ).values(
    	'pk',
    	'status',
    	'address',
    	'name',
    )
    
    협력사쿼리 = 협력사.objects.annotate(
    	status=Value(None, output_field=models.CharField()),
    ).values(
    	'pk',
    	'address',
    	'name',
    )
    
    유니온쿼리 = 가맹점쿼리.union(협력사쿼리)
    print(유니온쿼리)

SQL 결과

    (
    	SELECT
    		id
    		status
    		name
    		addr as address
    )
    union
    (
    	SELECT
    		id
    		address
    		name
    		null as status
    )

idstatusnameaddress
1운영중가맹점1가맹점주소...
2운영중가맹점2가맹점주소...
1협력사주소..협력사1null
2협력사주소..협력사2null

협력사의 필드 순서가 이상하게 나오는 걸 알 수 있다.

유니온 쿼리의 순서를 보면 address, status 의 순서가 Values 에 작성된 것과 다르다. 결론은 annotate 에 정의된 필드는 반드시 SELECT 절의 하위에 작성된다.

해결책

Annotate 된 필드는 SELECT 절의 하위에 나오게되니, 양쪽의 Annotate 필드를 맞추면 된다.
근데 여전히 문제가 하나 더 있다. address=F('address') 사용할 수 없다. Django 에서는 같은 이름의 필드가 이미 존재하면 annotate 하지 못하기 때문이다.

    가맹점쿼리 = 가맹점.objects.annotate(
    	address=F('addr'),
        _status=F('status'),
    ).values(
    	'pk',
    	'address',
    	'name',
    )
    
    협력사쿼리 = 협력사.objects.annotate(
    	_address=F('address'),
        status=Value(None, output_field=models.CharField()),
    ).values(
    	'pk',
    	'_address',
    	'name',
    )
    
    유니온쿼리 = 가맹점쿼리.union(협력사쿼리)
    print(유니온쿼리)

SQL 결과

    (
    	SELECT
    		id
    		name
    		addr as address
            status as _status
    )
    union
    (
    	SELECT
    		id
    		name
    		address as _address
            null as status
    )

결과는 제대로 나오게된다. 근데 필드 이름이 문제가된다..

profile
Qué será, será

0개의 댓글