当前位置: 首页 > 面试题库 >

将LEFT OUTER JOIN查询转换为Django ORM queryset / query

袁飞鹏
2023-03-14
问题内容

给定PostgreSQL 9.2.10,Django 1.8,python 2.7.5和以下模型:

class restProdAPI(models.Model):
    rest_id = models.PositiveIntegerField(primary_key=True)
    rest_host = models.CharField(max_length=20)
    rest_ip = models.GenericIPAddressField(default='0.0.0.0')
    rest_mode = models.CharField(max_length=20)
    rest_state = models.CharField(max_length=20)


class soapProdAPI(models.Model):
    soap_id = models.PositiveIntegerField(primary_key=True)
    soap_host = models.CharField(max_length=20)
    soap_ip = models.GenericIPAddressField(default='0.0.0.0')
    soap_asset = models.CharField(max_length=20)
    soap_state = models.CharField(max_length=20)

以下原始查询返回的正是我要寻找的内容:

SELECT
    app_restProdAPI.rest_id, app_soapProdAPI.soap_id, app_restProdAPI.rest_host, app_restProdAPI.rest_ip, app_soapProdAPI.soap_asset, app_restProdAPI.rest_mode, app_restProdAPI.rest_state
FROM
    app_soapProdAPI
LEFT OUTER JOIN
    app_restProdAPI
ON
    ((app_restProdAPI.rest_host = app_soapProdAPI.soap_host)
OR
    (app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip))
WHERE 
    app_restProdAPI.rest_mode = 'Excluded';

返回如下:

 rest_id | soap_id |   rest_host   |     rest_ip    | soap_asset | rest_mode | rest_state
---------+---------+---------------+----------------+------------+-----------+-----------
   1234  |  12345  | 1G24019123ABC | 123.123.123.12 |  A1234567  | Excluded  |     Up

使用Django的模型和orm结构进行这项工作的最佳方法是什么?

我一直在寻找完全没有关系地连接两个表的可能方法,但是似乎没有一种干净或有效的方法来做到这一点。我也尝试过寻找在django中进行左外部联接的方法,但同样,文档稀疏或难以破解。

我知道我可能必须使用Q对象来执行我在那里的or子句。另外,我已经研究了关系,它看起来foreignkey()可能可行,但是我不确定这是否是最好的方法。任何和所有帮助将不胜感激。先感谢您。

编辑1

到目前为止,Todor提供了使用有效的INNER JOIN的解决方案。如果有人可以破译在线原始html的混乱局面,我可能会在
这里 找到解决方案。

编辑2

有没有办法像我上面给出的查询(Todor的答案)那样过滤一个字段(某物=“某物”)?我尝试了以下操作,但是即使我的等效postresql查询按预期工作,它仍包含所有记录。似乎我无法在所需要的地方拥有所有内容,因为当我删除or语句之一并仅执行and语句时,它将应用排除的过滤器。

soapProdAPI.objects.extra(
    select = {
        'rest_id'    : 'app_restprodapi.rest_id',
        'rest_host'  : 'app_restprodapi.rest_host',
        'rest_ip'    : 'app_restprodapi.rest_ip',
        'rest_mode'  : 'app_restprodapi.rest_mode',
        'rest_state' : 'app_restprodapi.rest_state'
    },
    tables = ['app_restprodapi'],
    where  = ['app_restprodapi.rest_mode=%s \
               AND app_restprodapi.rest_host=app_soapprodapi.soap_host \
               OR app_restprodapi.rest_ip=app_soapprodapi.soap_ip'],
    params = ['Excluded']
    )

编辑3 /当前解决方案

迄今为止,Todor已使用INNER
JOIN提供了最完整的答案,但希望该问题能引起人们对如何实现此目标的思考。由于这似乎并非固有的可能性,因此欢迎任何和所有建议,因为它们可能会导致更好的解决方案。就是说,使用Todor的答案,我能够完成所需的确切查询:

restProdAPI.objects.extra(
    select = {
        'soap_id'    : 'app_soapprodapi.soap_id',
        'soap_asset' : 'app_soapprodapi.soap_asset'
    },
    tables = ['app_soapprodapi'],
    where  = ['app_restprodapi.rest_mode = %s',
              'app_soapprodapi.soap_host = app_restprodapi.rest_host OR \
               app_soapprodapi.soap_ip   = app_restprodapi.rest_ip'
    ],
    params = ['Excluded']
    )

TLDR

我想将此PostGreSQL查询转换为Django提供的ORM,而
无需使用.raw()或任何原始查询代码
。如果这样做很方便,并且从性能的角度来看,这是最好的方法,那么我完全愿意将模型更改为具有外键。如果在设计方面有帮助,我将使用与django-
datatables-view一起返回的对象。


问题答案:

用INNER JOIN解决

如果您只能soapProdAPI's使用包含相应的内容restProdAPI _(根据您的join语句-

由host或ip链接)_。您可以尝试以下操作:

soapProdAPI.objects.extra(
    select = {
        'rest_id'   : "app_restProdAPI.rest_id",
        'rest_host' : "app_restProdAPI.rest_host",
        'rest_ip'   : "app_restProdAPI.rest_ip",
        'rest_mode' : "app_restProdAPI.rest_mode",
        'rest_state': "app_restProdAPI.rest_state"
    },
    tables = ["app_restProdAPI"],
    where = ["app_restProdAPI.rest_host = app_soapProdAPI.soap_host \
              OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip"]
)

如何过滤更多?

由于我们正在使用,.extra我建议您仔细阅读文档。通常,我们无法使用dict中的.filter某些字段select,因为它们不是的一部分,soapProdAPI而Django无法解析它们。我们必须坚持使用where
kwargin .extra,并且因为它是一个列表,所以我们最好只添加另一个元素。

    where = ["app_restProdAPI.rest_host = app_soapProdAPI.soap_host \
              OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip",
             "app_restProdAPI.rest_mode=%s"
    ],
    params = ['Excluded']

重复子查询

如果您真的需要所有soapProdAPI's内容,无论它们是否具有对应的内容,restProdAPI我都只能想到一个丑陋的示例,其中subquery您需要的每个字段都重复一个。

soapProdAPI.objects.extra(
    select = {
        'rest_id'   : "(select rest_id from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
        'rest_host' : "(select rest_host from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
        'rest_ip'   : "(select rest_ip from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
        'rest_mode' : "(select rest_mode from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
        'rest_state': "(select rest_state from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)"
    },
)


 类似资料:
  • 问题内容: 我想将以下SQL查询转换为Elasticsearch之一。谁能帮上忙 我尝试了以下方法: 但不确定我是否做对了,因为它无法验证结果。似乎要在聚合内添加查询。 问题答案: 假设您使用Elasticsearch 2.x,则有可能在Elasticsearch中 具有 -semantics。我不知道2.0之前的可能性。 您可以使用新的Pipeline Aggregation Bucket Se

  • 问题内容: 多亏了Erwin Brandstetter在我之前的问题“具有has_many关系的订单”中的帮助,我的SQL查询才能正常工作。 如何将该SQL转换为ActiveRecords或AREL查询以在范围中使用? 我最近来的是在朋友的帮助下… …这给了我一个错误: 更新: 我之前的问题对相关的架构和查询有完整的描述。但是基本上Articles have_many Metrics和一个Metr

  • 问题内容: 实际上,我有1个查询,但无法将其转换为CakePHP查询格式。 当我将此查询转换为CakePHP时,会出现如下错误: 问题答案: 您可以轻松地在Cake上运行直接SQL查询,例如:$ this-> Picture-> query(“ SELECT * FROM pictures LIMIT 2;”); 或尝试与此类似的东西: ..确保您已正确链接Esl_Userresults和Esl_

  • 我有两个表,它们通过一个外键来维护它们之间的父子关系。查询如下所示。我想在使用jpa的同时使用标准版。所以有人可以帮助我使用标准版吗 表“child”的“notification\u id\u child”列是外键,并引用表“parent”的主键。

  • 我使用了cakephp Mysql到mongodb查询组件,即将Mysql查询转换到mongodb中,但是当查询有多个括号时代码停止工作,我还尝试将http://www.querymongo.com/site上的查询转换为相同的问题,

  • 问题内容: 我在SQL Server 2008中具有下表: 我需要创建以下输出的查询: 列可以固定为[Mitarbeiter1]-[Mitarbeiter5],因为每个Filiale的行数不能超过5行。 非常感谢您的帮助! 问题答案: 使用SQL Server 2008,将Pivot和Rank函数组合在一起,可以为每个雇员数量提供理想的结果。首先,我们为每个分支中的每个员工分配一个ID,从每个新分

  • 问题内容: 关于我之前的问题ElasticSearchQuery,其中给出了映射和doc示例,我想将此MySql查询转换为Elasticsearch。这是mysql查询 期待您的帮助 问题答案: 以下查询将为您提供帮助。请注意,在映射中,您已经提到了上述查询。 尽管如此,我还是利用了它,使其与映射保持一致。 我使用过术语查询,术语查询和多匹配查询的变体。 请注意,我已经在字段上使用了Term Qu

  • 问题内容: 我有一个如下所示的表。我的问题是:如何将列转换为行?我正在使用Microsoft SQL Server 我需要像下面的操作 怎么做?谢谢 问题答案: 您的资料 询问 结果集