【问题标题】:Filtering queryset by number of many-to-one relationships with a raw SQL query使用原始 SQL 查询按多对一关系的数量过滤查询集
【发布时间】:2018-05-17 10:05:56
【问题描述】:

我正在创建一个资源页面,我有以下模型:

class Tag(models.Model):
    title = models.CharField(max_length=50, blank=False, unique=True, error_messages={'unique':"THis tag already exists."}) 

class Link(models.Model):
    title = models.CharField(max_length=100, blank=False)
    tag = models.ForeignKey(Tag, on_delete=models.CASCADE, null=False, blank=False)

哪些字段较多,但与本题无关。

这个资源页面的问题是仍然出现没有与它们建立关系的链接的标签,我只希望它们下至少有一个链接的标签出现。

现在,我已经设法通过这个查询集过滤来做到这一点:

tags = Tag.objects.all().filter(link__isnull=False).order_by("title").distinct()

在我的views.py 中工作正常,我想要的已经完成了。请注意,“distinct”是必需的,这样它就不会返回重复的查询。

我对 MySQL 的经验很少,只用它和 PHP 构建了非常简单的应用程序。我现在知道它在 SQLite 下是如何工作的,我什至不知道如何在 MySQL 下做到这一点。

根据我的(非常非正式的)逻辑,它的功能是这样的(请原谅我扼杀了语言):

SELECT * FROM Tags WHERE NUMBER_OF_RELATIONSHIPS IS GREATER THAN 0

我的问题实际上是如何通过原始 SQL 查询来实现这一点,无论是在 SQLite 还是 MySQL 下?

【问题讨论】:

  • 我对 Django 将我从 SQL 中解放出来的程度感到有些困扰。当然,它有助于提高工作效率,但我感觉像是在学习轮子之类的东西。

标签: python mysql sql django sqlite


【解决方案1】:

您想要获取具有多个关系(即链接)的所有标签,对吗?如果是这样,您可以将其用作原始 SQL:

SELECT *
FROM <Tag_TableName>
WHERE <Tag_PK_Field> IN (
  -- Get Tag Ids with more than one entry in Link table
  SELECT <Tag_FK_Field>
  FROM <Link_TableName>
  HAVING COUNT(*) >= 1 -- Only return rows that have multiple entries per same tag
  GROUP BY <Tag_FK_Field>
)

如果这不起作用,您可能需要将内部 SELECT 包装在另一个 SELECT 中,以便过滤掉具有多个“链接”条目的“标签”。

我认为 Django 将 PK 字段名称默认为“id”,因此您的实际原始查询可能更接近于:

SELECT *
FROM "<proj_name>_tag"
WHERE "id" IN (
  SELECT "id"
  FROM "<proj_name>_link"
  HAVING COUNT(*) >=1
  GROUP BY "id"
)

【讨论】:

  • 是的,我的逻辑存在缺陷。它实际上是greater than 0,但你的想法很合适。 Django 不能完全使用它,但现在我理解了它背后的逻辑,这就是我想要的。谢谢!
  • 没问题 :) 为什么不能在 Django 中使用它?我知道您对 Django 为“编写” SQL 所施加的训练轮的感受。这很烦人。
猜你喜欢
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-16
  • 2019-09-20
  • 2015-12-06
  • 2017-07-15
  • 1970-01-01
相关资源
最近更新 更多