2017-09-04 11 views
2

私はジャンゴを学んでいる、と私は少し問題が直面している:私は行が関連しているモデルを持っているGrouppingとDjangoのモデルに集約する関連レコード

を、と私は合計を取得したいのですが第2の列の値によってグループ化された関連する行の列の第2の列を含む。

私が働いているモデルのは、以下の通りである:

class Integrante(models.Model): 
    nombre = models.CharField(max_length=80, db_index=True) 

class EstadoCuenta(models.Model): 
    num_edc = models.PositiveIntegerField(validators=[MinValueValidator(1),]) 
    fecha_edc = models.DateField(null=True, db_index=True) 

class Movimiento(models.Model): 
    TIPOS_MOVIMIENTO = (
     # Choices for column 'tipo' 
    ) 
    estado_cuenta = models.ForeignKey(EstadoCuenta, on_delete=models.CASCADE) 
    integrante = models.ForeignKey(Integrante, on_delete=models.CASCADE) 
    fecha = models.DateField(db_index=True) 
    tipo = models.SmallIntegerField(db_index=True, choices=TIPOS_MOVIMIENTO) 
    descripcion = models.CharField(max_length=200, blank=True) 
    importe = models.DecimalField(max_digits=8, decimal_places=2) 

    class Meta: 
     ordering = ['integrante', 'fecha', 'tipo', 'pk'] 

私は、次の試してみた:

for x in edc.movimiento_set.values('integrante').annotate(Sum('importe')): 
    print(x) 

# {'integrante': 28, 'importe__sum': Decimal('-20.00')} 
# {'integrante': 28, 'importe__sum': Decimal('23.00')} 
# {'integrante': 28, 'importe__sum': Decimal('9.60')} 
# {'integrante': 28, 'importe__sum': Decimal('20.00')} 
# {'integrante': 28, 'importe__sum': Decimal('-0.60')} 
# {'integrante': 24, 'importe__sum': Decimal('96.00')} 
# {'integrante': 24, 'importe__sum': Decimal('28.80')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('28.80')} 
# {'integrante': 24, 'importe__sum': Decimal('96.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('288.00')} 
# {'integrante': 24, 'importe__sum': Decimal('144.00')} 
# {'integrante': 24, 'importe__sum': Decimal('19.20')} 
# {'integrante': 24, 'importe__sum': Decimal('-510.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('48.00')} 
# {'integrante': 24, 'importe__sum': Decimal('35.00')} 
# {'integrante': 24, 'importe__sum': Decimal('235.00')} 
# {'integrante': 24, 'importe__sum': Decimal('-0.80')} 
# ... 
:しかし

edc = EstadoCuenta.objects.filter(grupo__nombre_grupo='A group').latest() 
edc.movimiento_set.values('integrante').annotate(Sum('importe')) 

、私は以下の結果を得ています

私が得ようとしている結果は、このようなものです(データベースサーバーで直接行われます):

select integrante_id, sum(importe) 
from core_movimiento 
where estado_cuenta_id=233 
group by integrante_id; 

-- | integrante_id | sum(importe) | 
-- +---------------+--------------+ 
-- |   24 |  844.00 | 
-- |   25 |   0.00 | 
-- |   26 |   0.00 | 
-- |   27 |  -232.00 | 
-- |   28 |  32.00 | 
-- |   29 |   0.00 | 
-- |   30 |  20.00 | 

正しい方向で私を指摘できますか?

私は、Python 3.6とDjangoを使用しています1.11

ボーナス

私も列tipoの値に応じて、列に分離importeの合計を取得したいと思います。 SQLで、私はこれを得ることができます:

select integrante_id 
    , sum(case when tipo=1 then importe else 0 end) as pagos 
    , sum(case when tipo in (11, 12) then importe else 0 end) as ventas 
    , sum(case when tipo in (70, 71) then importe else 0 end) as paquetes 
    , sum(case when tipo=99 then importe else 0 end) as ajustes 
    , sum(importe) as total 
from core_movimiento 
where estado_cuenta_id = 233 
group by integrante_id; 

-- | integrante_id | pagos | ventas | paquetes | ajustes | total | 
-- +---------------+---------+---------+----------+---------+---------+ 
-- |   24 | -510.00 | 1084.80 | 270.00 | -0.80 | 844.00 | 
-- |   25 | -35.00 | 0.00 | 35.00 | 0.00 | 0.00 | 
-- |   26 | -20.00 | 0.00 | 20.00 | 0.00 | 0.00 | 
-- |   27 | -422.00 | 190.00 |  0.00 | 0.00 | -232.00 | 
-- |   28 | -20.00 | 32.60 | 20.00 | -0.60 | 32.00 | 
-- |   29 | -200.00 | 0.00 | 200.00 | 0.00 | 0.00 | 
-- |   30 | 0.00 | 0.00 | 20.00 | 0.00 | 20.00 | 

アイデア?

+0

あなたのモデル 'meta'に' ordering'がありますか? –

+1

これは大きな質問です。特にボーナス部分!良い答えは、django ORMを使ってデータベースに多くの往復をせずにこれを行うでしょう。あなたはdjango ORMを台無しにすると答えてもらえますか? djangoでraw SQLクエリを作成するのと同じように:https://docs.djangoproject.com/en/1.11/topics/db/sql/ – Tico

+0

@BearBrown 'Movimiento'に' Meta'クラスを追加しました。私は注文に ''integrante''だけを残すべきですか? – Barranka

答えて

1

答えを更新します2番目の質問は、django 1.8が持っているので、新しい答えを追加してください。conditional-expressions

from django.db.models import Sum, When, Case, IntegerField, F 

edc.movimiento_set.values('integrante' 
    ).annotate(total=Sum('importe') 
    ).annotate(pagos=Sum(
     Case(
      When(tipo=1, then=F('importe')), 
      default=0, 
      output_field=IntegerField() 
      ) 
     ) 
    ).annotate(ventas=Sum(
     Case(
      When(tipo__in=(11, 12), then=F('importe')), 
      default=0, 
      output_field=IntegerField() 
      ) 
     ) 
    ).annotate(paquetes=Sum(
     Case(
      When(tipo__in=(70, 71), then=F('importe')), 
      default=0, 
      output_field=IntegerField() 
      ) 
     ) 
    ).annotate(ajustes=Sum(
     Case(
      When(tipo=99, then=F('importe')), 
      default=0, 
      output_field=IntegerField() 
      ) 
     ) 
    ).order_by() 

大丈夫です。

+0

印象的な!私は両方の答えを受け入れたいと思います!ありがとうございました! – Barranka

2

あなたが最初はただで空の順番を追加必要があります。デフォルトで

edc.movimiento_set.values('integrante').annotate(Sum('importe')).order_by() 
#                ^^^^^^^^^^ 

、私は思うのボーナスのためのフィールドordering-or-order-by

を注文することにより、グループを追加Djangoのあなたのために、後で

関連する問題