Django order_by导致LEFT JOIN

时间:2011-05-09 23:14:04

标签: sql django django-models django-orm

有人可以告诉我为什么当我添加order_by()查询时,会将输出从INNER JOIN更改为LEFT OUTER JOIN吗?

有没有办法保留INNER JOIN - ness?

data = models.RetailSalesFact.objects.values('customer_key__customer_state', 
                                             'date_key__calendar_month_name')
data = data.filter(date_key__calendar_year=year)
data = data.annotate(sales=Sum('sales_quantity'))
data = data.order_by('date_key__calendar_month_name')

之前:

SELECT Customer_Dimension.Customer_State, Date_Dimension.Calendar_Month_Name,
       SUM(Retail_Sales_Fact.Sales_Quantity) AS sales 
    FROM Retail_Sales_Fact  
    INNER JOIN Customer_Dimension 
        ON (Retail_Sales_Fact.Customer_Key = Customer_Dimension.Customer_Key) 
    INNER JOIN Date_Dimension 
        ON (Retail_Sales_Fact.Date_Key = Date_Dimension.Date_Key) 
    WHERE Date_Dimension.Calendar_Year = ?  
    GROUP BY Customer_Dimension.Customer_State, 
             Date_Dimension.Calendar_Month_Name 
    ORDER BY Date_Dimension.Calendar_Month_Name ASC

后:

SELECT Customer_Dimension.Customer_State, Date_Dimension.Calendar_Month_Name, 
       SUM(Retail_Sales_Fact.Sales_Quantity) AS sales 
    FROM Retail_Sales_Fact 
    INNER JOIN Customer_Dimension 
        ON (Retail_Sales_Fact.Customer_Key = Customer_Dimension.Customer_Key) 
    LEFT OUTER JOIN Date_Dimension 
        ON (Retail_Sales_Fact.Date_Key = Date_Dimension.Date_Key) 
    WHERE Date_Dimension.Calendar_Year = ?  
    GROUP BY Customer_Dimension.Customer_State, 
             Date_Dimension.Calendar_Month_Name 
    ORDER BY Date_Dimension.Calendar_Month_Name ASC

2 个答案:

答案 0 :(得分:1)

我猜ORM正在做一个LEFT JOIN,因为它无法判断INNER JOIN的限制是否比排序子句更多或更少限制。因为它认为它需要订购每条记录,无论它是否匹配。

您可以使用Raw SQL强制INNER JOIN。或者您可以通过在order_by之前应用filter来欺骗ORM。

答案 1 :(得分:1)

您在外部表上放置了一个过滤器(date_dimension__calendar_year = year),因此无论您使用内部联接还是左外部联接,结果集之间都没有区别。

在中间结果集上处理order-by - 如果在内连接表上完成,则必须在组合表之后完成 - 这意味着读取一个:组合记录;阅读二:订购组合记录。

但是如果order-by仅在外部连接表上完成,在这种情况下就是你所要求的,那么你的查询优化器可能能够避免两次读取整个集合,而是,只读两次外表。您的优化器可能会认为这可以节省处理能力。

这只是猜测。您的结果集应该以相同的方式转换。我想知道你是否可以两种方式计时,看看哪一个需要更长时间。