Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como faço para converter esse SQL complexo em uma consulta de modelo Django?


EDITAR: Consegui reformar a solução usando subconsultas do Django.

Podemos traduzir a consulta para o Django ORM usando o aggregates with SubQuery expressions :

  1. Crie uma subconsulta para recuperar o close mais baixo para 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')
    

    • Detalhamento:
      • filter o conjunto de consultas para obter apenas as ações com trading_date >= '2017-05-04' .
      • "GROUP BY" stock__symbol (exemplos de group by no Djnago:GROUP BY ... MIN/MAX , GROUP BY ... COUNT/SUM ).
      • annotate o mais baixo (low ) preço para cada elemento.
      • filter o queryset novamente para obter apenas os objetos com um low campo que ocorre em trading_date >= '2018-04-30' .

    • Resultado intermediário:

      Embora não possamos obter um resultado neste estágio, a subconsulta ficará assim:
      [
          {'stock__symbol': 'A', 'low': Decimal('105.00000')},            
          {'stock__symbol': 'C', 'low': Decimal('90.00000')}
      ]
      

      Falta a trading_date .

  2. Utilize a subconsulta para recuperar o 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')
    

    • Detalhamento:
      • lows.values('stock__symbol') e lows.values('low') recuperam os respectivos valores da subconsulta.
      • filter o conjunto de consultas em relação aos lows valores de subconsulta. Também filter em relação à data especificada para eliminar close baixo preços que ocorrem antes dessa data.
      • Obter os values especificados .
      • Ordenar o resultado por stock__symbol (por padrão 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'
          }
      ]