Django order_by вызывает LEFT JOIN - PullRequest
7 голосов
/ 10 мая 2011

Может кто-нибудь сказать мне, почему, когда я добавляю order_by() запрос, который получает вывод, изменяется с INNER JOIN на LEFT OUTER JOIN?

Есть ли способ сохранить INNER JOIN -несс?

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 ]

1 голос
/ 06 июля 2011

Вы помещаете фильтр во внешнюю таблицу (date_dimension__calendar_year = year), поэтому не будет никакой разницы между набором результатов, используете ли вы внутреннее соединение или левое внешнее соединение.

Порядок обрабатывается в промежуточном наборе результатов - если он выполняется для таблиц с внутренним соединением, то он должен выполняться после объединения таблиц, что означает чтение один: объединить записи; прочитайте два: закажите объединенные записи.

Но если упорядочение выполняется только для таблицы с внешним соединением, что в этом случае является единственным, о чем вы просите, тогда ваш оптимизатор запросов сможет избежать чтения всего набора дважды, и вместо этого , только прочитайте внешнюю таблицу дважды. Ваш оптимизатор может признать это как экономию вычислительной мощности.

Это всего лишь предположение. Ваш набор результатов должен получиться таким же в любом случае. Интересно, вы могли бы рассчитать время в обоих направлениях и посмотреть, какой из них займет больше времени?

1 голос
/ 18 июня 2011

Я предполагаю, что ORM выполняет LEFT JOIN, потому что не может определить, является ли ограничение INNER JOIN где-либо более или менее ограничивающим, чем условие упорядочения.Поскольку он считает, что необходимо упорядочить каждую запись, независимо от того, соответствует она или нет.

Вы можете принудительно INNER JOIN использовать Raw SQL .Или, может быть, вы можете обмануть ORM, применив order_by перед filter?

...