代码之家  ›  专栏  ›  技术社区  ›  shanyu

使用Django ORM基于最大值获取单个子行

  •  3
  • shanyu  · 技术社区  · 15 年前

    我有一个模型,“市场”与另一个模型“合同”有一对多的关系:

    class Market(models.Model):
        name = ...
        ...
    
    class Contract(models.Model):
        name= ...
        market = models.ForeignKey(Market, ...)
        current_price = ...
    

    我想随合同一起去拿市场上的物品,每件物品的最高价格。这是我通过原始SQL实现的方式:

    SELECT M.id as market_id, M.name as market_name, C.name as contract_name, C.price 
    as price from pm_core_market M INNER JOIN
        (SELECT market_id, id, name, MAX(current_price) as price 
            FROM pm_core_contract GROUP BY market_id) AS C
    ON M.id = C.market_id
    

    有没有一种不用SQL实现的方法?如果有,在性能方面应该优先选择哪一个?

    1 回复  |  直到 15 年前
        1
  •  9
  •   Ayman Hourieh    15 年前

    Django 1.1(目前为beta版)增加了 aggregation

    from django.db.models import Max, F
    
    Contract.objects.annotate(max_price=Max('market__contract__current_price')).filter(current_price=F('max_price')).select_related()
    

    这将生成以下SQL查询:

    SELECT contract.id, contract.name, contract.market_id, contract.current_price, MAX(T3.current_price) AS max_price, market.id, market.name
    FROM contract LEFT OUTER JOIN market ON (contract.market_id = market.id) LEFT OUTER JOIN contract T3 ON (market.id = T3.market_id)
    GROUP BY contract.id, contract.name, contract.market_id, contract.current_price, market.id, market.name
    HAVING contract.current_price =  MAX(T3.current_price)