2017-01-07 1 views
1

2 개의 ForeignKeys에 의존하는 쿼리를 작성하려고합니다.하나의 SQL 또는 Django ORM 명령에서이 작업을 수행하는 방법은 무엇입니까?

많은 선두로부터 객체 (외래 키)를 가질 수 제품 있습니다. 발생 개체 개체가 많을 수도 검색 개체 (ForeignKey 너무). 그 속성 가격날짜 속성에 따라, (가격이 OneToOneField입니다) 널 (null)이 아닌 경우

는 지금은, 객체 마지막 스캔의 모든 선두로부터 얻을 싶어요.

순진 방법 :

product = Product.objects.first() 
scans = [] 
for occ in product.occurences.all(): 
    scan = occ.scans.filter(price__isnull=False).orderby("-datetime").first() 
    if scan: 
     scans.append(scan) 

>>> result is scans list 

이 방법은 많은 단점이있다. 한 제품은 수백 건의 스캔 작업과 수백만 회의 스캔 작업을 수행 할 수 있으므로 작업을 수행하는 데이터베이스가 가장 좋습니다.

그래서이 작업을 수행 할 수있는 쿼리를 찾고 있습니다.

Scan.objects.filter(occurence__product=product,price__isnull=False) 

이렇게하면 null 가격 속성이없는 제품의 모든 스캔이 반환됩니다. 내가 GroupBy를 사용해야한다고 생각하지만 어떻게해야할지 모르겠다.

+0

왜 GROUP BY가 필요한가요? 주석이 없으며'Scan '에서 모든 열을 선택하고 있으므로 어떤 영향을 미치는지 보지 못합니다. 'GROUP BY'가 필요하면 Django가 그것을 자동으로 쿼리에 추가합니다. – knbk

+0

필자는 스캔을 스캔하여 그룹화해야한다고 생각한 다음 각 그룹에서 최신 스캔을 가져와야합니다. 아마도 나는 GROUP BY가 필요하지 않을지도 모른다. 이 문제를 해결하는 방법을 알고 있습니까? –

답변

0

나는이 모델 아키텍처 바랍니다 ..

class Product(models.Model): 
    # fields 

class Occurence(models.Model): 
    # some other fields 
    product = models.ForeignKey(Product) 


class Scan(models.Model): 
    # a few other fields 
    occurence = models.ForeignKey(Occurence) 

이 경우, 당신은 그것은 당신이 경우 확인되는 모델에서 명확하지 않습니다이

product = Product.objects.get(pk=product_id) 
occurences = product.occurence_set.all() 
scans = Occurence.scan_set.filter(occurence__in = occurences).order_by('-date_field')[:n] 

을 할 수 있어야 가격은 null입니다. 발생 또는 스캔 중 해당 모델에 가격 필터를 추가 할 수 있습니다.

order_by 필드별로 데이터를 정렬합니다. 장고에서는 슬라이싱 ([: n]은 MySQL의 경우 limit이거나 SQL의 경우 top)입니다.

각 occurance

이 데이터가 bulk_create 삽입되지 않은 경우에만 작동합니다 최신 요소를 가져 오기/데이터가 동시에 테이블에 insterted된다.

Occurence.scan_set.filter(occurence__in = occurences).annotate(latest_scan=Max('occurance__scan__date_field')).filter(date_field=F('latest_scan')) 

꽤 많은 스캔 인스턴스가 있다고 말한대로 이상적으로 시간 필드 여야합니다.

+0

예, 모델 아키텍처가 좋습니다. 대답에는 두 가지 문제가 있습니다. 첫 번째는 스캔 수를 매우 높게 (수백만) 할 수 있으므로 데이터베이스에서 모두 선택할 수 없다는 것입니다. 또 다른 한 가지는 마지막 스캔 (최저 datetime) 만 원한다는 것입니다. –

+0

나는 order_by를 추가하고 쿼리에서 최신 스캔을 선택하기 위해 슬라이싱합니다. 추가해야 할 것이 있으면 알려주세요. –

+0

첫 번째 문제는 모든 스캔이 메모리에로드된다는 것입니다. 두 번째 문제는 올바른 결과를 반환하지 않는다는 것입니다 (한 번에 n 개의 최신 스캔을 반환 할 수 있습니다.) –