Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment convertir ce SQL complexe en une requête de modèle Django ?

MODIF : J'ai réussi à réformer la solution en utilisant les sous-requêtes Django.

Nous pouvons traduire la requête en ORM Django en utilisant aggregates with SubQuery expressions :

  1. Créer une sous-requête pour récupérer le close le plus bas pour chaque symbol :

    from django.db.models import OuterRef, Subquery, Min     
    
    lows = StockHistory.objects.filter(
        stock=OuterRef('stock'), 
        trading_date__gte='2017-05-04'
    ).values('stock__symbol')
    .annotate(low=Min('close'))
    .filter(trading_date__gte='2018-04-30')
    
    • Répartition :

      • filter le jeu de requêtes pour obtenir uniquement les actions avec trading_date >= '2017-05-04' .
      • "GROUPER PAR" stock__symbol (exemples de group by dans Djnago :GROUP BY ... MIN/MAX , GROUP BY ... COUNT/SUM ).
      • annotate le plus bas (low ) prix à chaque élément.
      • filter le queryset à nouveau pour n'obtenir que les objets avec un low champ apparaissant le trading_date >= '2018-04-30' .
    • Résultat intermédiaire :

      Bien que nous ne puissions pas obtenir de résultat à ce stade, la sous-requête ressemblera à ceci :

      [
          {'stock__symbol': 'A', 'low': Decimal('105.00000')},            
          {'stock__symbol': 'C', 'low': Decimal('90.00000')}
      ]
      

      Il nous manque la trading_date .

  2. Utilisez la sous-requête pour récupérer le StockHistory spécifique objets :

    StockHistory.objects.filter(
        stock__symbol=Subquery(lows.values('stock__symbol')),
        close=Subquery(lows.values('low')),
        trading_date__gte='2018-04-30'
    ).values('stock__symbol', 'trading_date', 'close')
    .order_by('stock__symbol')
    
    • Répartition :

      • lows.values('stock__symbol') et lows.values('low') récupèrent les valeurs respectives de la sous-requête.
      • filter le jeu de requêtes par rapport aux lows valeurs de sous-requête. Aussi filter par rapport à la date spécifiée afin d'éliminer les faibles close prix antérieurs à cette date.
      • Obtenir les values spécifiées .
      • Ordonner le résultat par stock__symbol (par défaut ascending ).
    • Résultat :

      [
          {
              'close': Decimal('105.00000'), 
              'trading_date': datetime.date(2018, 5, 3), 
              'stock__symbol': 'A'
          }, 
          {
              'close': Decimal('90.00000'), 
              'trading_date': datetime.date(2018, 5, 4), 
              'stock__symbol': 'C'
          }
      ]