【问题标题】:Django join-like query with no where condition没有where条件的Django join-like查询
【发布时间】:2018-03-15 10:45:14
【问题描述】:

假设我在 Django 中有 3 个模型

class Instrument(models.Model):
    ticker = models.CharField(max_length=30, unique=True, db_index=True)

class Instrument_df(models.Model):
    instrument = models.OneToOneField(
        Instrument,
        on_delete=models.CASCADE,
        primary_key=True,
    )

class Quote(models.Model):
    instrument = models.ForeignKey(Instrument, on_delete=models.CASCADE)

我只想查询与“DF”类型的工具相对应的所有报价。在 SQL 中,我会在字段 id 上执行 Quote 和 Instrument_df 的连接。

使用 Django 的 ORM 我出来了

Quote.objects.filter(instrument__instrument_df__instrument_id__gte=-1)

我认为这样做可以,但我看到两个缺点:

1) 我要加入 3 个表,而实际上不需要涉及表 Instrument。

2) 我必须插入微不足道的 id > -1 条件,该条件始终成立。这看起来非常人为。

这个查询应该怎么写?

谢谢!

【问题讨论】:

  • Instrument_df 中还有其他字段吗?如果不是,您的模型似乎是错误的......
  • @bruno 实际上,我只是删除了其他所有内容并保留了这些模型之间的引用。很抱歉没有澄清它。

标签: python django join


【解决方案1】:

假设Instrument_df 有其他字段未在 sn-p 中显示(否则此表无用,可以用Instrument 中的标志替换),可能的解决方案是使用子查询或两个查询:

# with a subquery
dfids = Instrument_df.objects.values_list("instrument", flat=True)
Quote.objects.filter(instrument__in=dfids)

# with two queries (can be faster on MySQL)
dfids = list(Instrument_df.objects.values_list("instrument", flat=True))
Quote.objects.filter(instrument__in=dfids)

这是否会比您的实际解决方案执行得更好取决于您的数据库供应商和版本(MySQL 以处理子查询非常糟糕而闻名,不知道是否仍然如此)和实际内容。

但是我认为这里最好的解决方案是一个简单的raw query - 这有点不那么便携,并且在架构更新的情况下可能需要更多的小心(提示:使用自定义管理器和将此查询编写为管理器方法,这样您就有了一个单一的事实——您不想用原始 sql 查询分散您的视图。

【讨论】:

  • 谢谢你,@bruno。我了解您的解决方案,我有类似的想法,但认为应该有一个更简单的单查询解决方案。我是数据库 ORM 的新手,到目前为止,在我看来它们比我预期的要复杂。
  • 好吧,使用原始查询是一种“单查询解决方案”。 wrt/ ORMs,Django 的设计目的是使 80% 的简单案例变得简单,并为您提供不那么简单的解决方案和更复杂案例的原始查询。其他一些 ORM 试图尽可能完整以涵盖 100% 的用例——从技术上讲,将整个 SQL 语言重新实现为 Python 对象——但最终对于 80% 的简单用例来说实际上至少要复杂两倍。
猜你喜欢
  • 2015-05-26
  • 1970-01-01
  • 2013-05-16
  • 2019-04-21
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多