sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo convierto este SQL complejo en una consulta de modelo de Django?

EDITAR: Logré reformar la solución usando subconsultas de Django.

Podemos traducir la consulta a Django ORM usando Django aggregates with SubQuery expressions :

  1. Cree una subconsulta para recuperar el close más bajo por cada 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')
    
    • Desglose:

      • filter el conjunto de consultas para obtener solo las acciones con trading_date >= '2017-05-04' .
      • "AGRUPAR POR" stock__symbol (ejemplos de group by en Djnago:GROUP BY ... MIN/MAX , GROUP BY ... COUNT/SUM ).
      • annotate el más bajo (low ) precio a cada elemento.
      • filter el conjunto de consultas nuevamente para obtener solo los objetos con un low campo que aparece en trading_date >= '2018-04-30' .
    • Resultado intermedio:

      Aunque no podemos obtener un resultado en esta etapa, la subconsulta se verá así:

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

      Nos falta la trading_date .

  2. Utilice la subconsulta para recuperar el StockHistory específico objetos:

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

      • lows.values('stock__symbol') y lows.values('low') recuperan los valores respectivos de la subconsulta.
      • filter el conjunto de consultas contra los lows valores de subconsulta. También filter contra la fecha especificada para eliminar el close bajo precios anteriores a esa fecha.
      • Obtener los values especificados .
      • Ordene el resultado por stock__symbol (por defecto ascending ).
    • Resultado:

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