Mysql
 sql >> Database >  >> RDS >> Mysql

Come posso convertire questo SQL complesso in una query del modello Django?

MODIFICA: Sono riuscito a riformare la soluzione utilizzando le sottoquery di Django.

Possiamo tradurre la query in Django ORM utilizzando aggregates with SubQuery expressions :

  1. Crea una sottoquery per recuperare la close più bassa per ogni 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')
    
    • Ripartizione:

      • filter il set di query per ottenere solo le azioni con trading_date >= '2017-05-04' .
      • "GRUPPO PER" stock__symbol (esempi di group by in Djnago:GROUP BY ... MIN/MAX , GROUP BY ... COUNT/SUM ).
      • annotate il più basso (low ) prezzo per ogni elemento.
      • filter il queryset di nuovo per ottenere solo gli oggetti con un low campo che si verifica il trading_date >= '2018-04-30' .
    • Risultato intermedio:

      Anche se non possiamo ottenere un risultato in questa fase, la sottoquery sarà simile a questa:

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

      Manca il trading_date .

  2. Utilizza la sottoquery per recuperare la specifica StockHistory oggetti:

    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')
    
    • Ripartizione:

      • lows.values('stock__symbol') e lows.values('low') recuperano i rispettivi valori dalla sottoquery.
      • filter il set di query contro i lows valori di sottoquery. Anche filter rispetto alla data specificata per eliminare la close bassa prezzi avvenuti prima di tale data.
      • Ottieni i values specificati .
      • Ordina il risultato per stock__symbol (per impostazione predefinita ascending ).
    • Risultato:

      [
          {
              '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'
          }
      ]