gpt4 book ai didi

python - 如何将这个复杂的 SQL 转换为 Django 模型查询?

转载 作者:可可西里 更新时间:2023-11-01 06:57:16 26 4
gpt4 key购买 nike

我正在编写一个 Python/Django 应用程序来进行一些股票分析。

我有两个非常简单的模型,如下所示:

class Stock(models.Model):
symbol = models.CharField(db_index=True, max_length=5, null=False, editable=False, unique=True)

class StockHistory(models.Model):
stock = models.ForeignKey(Stock, related_name='StockHistory_stock', editable=False)
trading_date = models.DateField(db_index=True, null=False, editable=False)
close = models.DecimalField(max_digits=12, db_index=True, decimal_places=5, null=False, editable=False)

class Meta:
unique_together = ('stock', 'trading_date')

这是我填充的虚拟数据:

import datetime
a = Stock.objects.create(symbol='A')
b = Stock.objects.create(symbol='B')
c = Stock.objects.create(symbol='C')
d = Stock.objects.create(symbol='D')

StockHistory.objects.create(trading_date=datetime.date(2018,1,1), close=200, stock=a)
StockHistory.objects.create(trading_date=datetime.date(2018,1,2), close=150, stock=a)
StockHistory.objects.create(trading_date=datetime.date(2018,1,3), close=120, stock=a)
StockHistory.objects.create(trading_date=datetime.date(2018,4,28), close=105, stock=a)
StockHistory.objects.create(trading_date=datetime.date(2018,5,3), close=105, stock=a)

StockHistory.objects.create(trading_date=datetime.date(2017,5,2), close=400, stock=b)
StockHistory.objects.create(trading_date=datetime.date(2017,11,11), close=200, stock=b)
StockHistory.objects.create(trading_date=datetime.date(2017,11,12), close=300, stock=b)
StockHistory.objects.create(trading_date=datetime.date(2017,11,13), close=400, stock=b)
StockHistory.objects.create(trading_date=datetime.date(2017,11,14), close=500, stock=b)

StockHistory.objects.create(trading_date=datetime.date(2018,4,28), close=105, stock=c)
StockHistory.objects.create(trading_date=datetime.date(2018,4,29), close=106, stock=c)
StockHistory.objects.create(trading_date=datetime.date(2018,4,30), close=107, stock=c)
StockHistory.objects.create(trading_date=datetime.date(2018,5,1), close=108, stock=c)
StockHistory.objects.create(trading_date=datetime.date(2018,5,2), close=109, stock=c)
StockHistory.objects.create(trading_date=datetime.date(2018,5,3), close=110, stock=c)
StockHistory.objects.create(trading_date=datetime.date(2018,5,4), close=90, stock=c)

我想找到过去一周内创下年度低点的所有股票。

但为了让这个问题更简单,假设我想找到自 '2017-05-04' 以来最低点发生在 '2018-04- 或之后的所有股票30'。下面是我为找到它而写的 SQL。它有效。

但我需要帮助来确定要编写什么 Django 查询才能获得与此 SQL 相同的结果。我该怎么做?

mysql> select
-> s.symbol,
-> sh.trading_date,
-> low_table.low
-> from
-> (
-> select
-> stock_id,
-> min(close) as low
-> from
-> stocks_stockhistory
-> where
-> trading_date >= '2017-05-04'
-> group by
-> stock_id
-> ) as low_table,
-> stocks_stockhistory as sh,
-> stocks_stock as s
-> where
-> sh.stock_id = low_table.stock_id
-> and sh.stock_id = s.id
-> and sh.close = low_table.low
-> and sh.trading_date >= '2018-04-30'
-> order by
-> s.symbol asc;
+--------+--------------+-----------+
| symbol | trading_date | low |
+--------+--------------+-----------+
| A | 2018-05-03 | 105.00000 |
| C | 2018-05-04 | 90.00000 |
+--------+--------------+-----------+
2 rows in set (0.02 sec)

最佳答案

编辑:我设法使用 Django 子查询改进了解决方案。

我们可以使用 Django 的 aggregates with SubQuery expressions 将查询转换为 Django ORM :

  1. 创建子查询以检索每个 symbol 的最低 close:

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

      • 过滤 查询集以仅获取 trading_date >= '2017-05-04' 的股票。
      • “GROUP BY”stock__symbol(Djnago 中的分组依据示例:GROUP BY ... MIN/MAXGROUP BY ... COUNT/SUM)。
      • 注释每个元素的最低 (low) 价格。
      • 再次
      • 过滤查询集以仅获取字段发生在trading_date >= '2018-04-30' 的对象。
    • 中间结果:

      虽然我们在这个阶段无法得到结果,但子查询将如下所示:

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

      我们缺少 trading_date

  2. 利用子查询检索特定的 StockHistory 对象:

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

      • lows.values('stock__symbol') 和 lows.values('low') 从子查询中检索相应的值。
      • filter 针对 lows 子查询值的查询集。还针对指定日期过滤,以消除该日期之前出现的低收盘价
      • 获取指定的
      • stock__symbol 对结果进行排序(默认为 升序)。
    • 结果:

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

关于python - 如何将这个复杂的 SQL 转换为 Django 模型查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50207218/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com