【问题标题】:Django self join , How to convert this query to ORM queryDjango 自联接,如何将此查询转换为 ORM 查询
【发布时间】:2014-12-26 12:22:24
【问题描述】:

如何将此查询转换为 django ORM 查询。

select T.node_id, ht, status, data from (
select id, Max(health_time) as ht, node_id from remote_sense_nodehealth group by node_id
) as T
join remote_sense_nodehealth on remote_sense_nodehealth.health_time=T.ht and remote_sense_nodehealth.node_id = T.node_id

其实我想根据其他列的值获取所有最新的值。

例如我的表是这样的 -

c1 | c2  | c3 
- - - - - - -
x | 1 AM | d1
x | 2 AM | d2
x | 3 AM | d3
y | 1 AM | d4
y | 2 AM | d5{

期望的输出:

[{c1: x, c2: 3AM, c3: d3}, {c1: y, c2: 2AM, c3: d5}]

【问题讨论】:

  • 这里为什么需要自行加入?理论上,分组和每组的最大值就足够了。
  • 我尝试使用 values('node_id') 并在 Max(Node_health) 处进行注释,但无法获取其他字段,即该表的“数据”。如果添加值,它也会在该字段上分组。
  • 部分原因是从已分组的行中获取“其他”字段通常没有意义

标签: python mysql django django-orm


【解决方案1】:

如果您的数据库支持分析,您可以执行以下操作:

q = NodeHealth.objects.extra(
    select={'row_num': "ROW_NUMBER() OVER (PARTITION BY c1 ORDER BY c2 DESC)"},
    where=["row_num=1"]
)

【讨论】:

    【解决方案2】:

    使用更规范化的数据模型,您会更轻松地执行此操作。考虑使用这样的方法:

    class NodeGroup(model.Model):
        pass
    
    class NodeHealth(model.Model):
        node_group = models.ForeignKey(NodeGroup, related_name='nodes')
        health_time = models.IntegerField()
        status = models.IntegerField()
    

    那么你可以这样做:

    from django.db.models import Max, F
    
    nodes = NodeHealth.objects.all().annotate(
        max_health_time=Max('node_group__nodes__health_time')
    ).filter(health_time=F('max_health_time'))
    

    不幸的是,如果多个节点具有相同的health_time 值,则返回的节点将具有重复项。您也许可以添加一个 .distinct('node_group_id') 来解决这个问题,但我不是 100% 肯定的。

    【讨论】:

      猜你喜欢
      • 2018-07-19
      • 2015-08-23
      • 2019-10-17
      • 2016-06-04
      • 2016-04-20
      • 2019-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多