2013-03-13 5 views
1

У меня есть этот запрос:Mysql - Помощь для оптимизации запроса

SELECT bi.id, 
     bi.location, 
     bi.expense_group, 
     bi.level, 
     bi.is_active, 
     bi.type, 
     full_name, 
     (bl.bud_amount)          AS BudgetAmount, 
     (COALESCE(((bl.bud_amount * 3) - ( 
        + bal.bal_amount1 + bal.bal_amount2 
        + bal.bal_amount3)), 0)) AS Difference, 
     (COALESCE(Round((+ bal.bal_amount1 + bal.bal_amount2 
          + bal.bal_amount3)/3), 0))  AS Average, 
     bal.bal_amount1          AS BAL1, 
     bal.bal_amount2          AS BAL2, 
     bal.bal_amount3          AS BAL3 
FROM (SELECT * 
     FROM budget_items bi 
     WHERE bi.location IS NOT NULL) AS bi 
     LEFT JOIN (SELECT budget_item_id, 
         Sum(CASE 
           WHEN budget_id = 21491 THEN amount 
          END) AS bud_amount 
        FROM budget_lines 
        GROUP BY budget_item_id) AS bl 
       ON bl.budget_item_id = bi.id 
     JOIN (SELECT budget_item_id, 
        Ifnull(Sum(CASE 
           WHEN balance_id = 12841 THEN amount 
           END), 0) AS bal_amount1, 
        Ifnull(Sum(CASE 
           WHEN balance_id = 18647 THEN amount 
           END), 0) AS bal_amount2, 
        Ifnull(Sum(CASE 
           WHEN balance_id = 18674 THEN amount 
           END), 0) AS bal_amount3 
      FROM balance_lines 
      GROUP BY budget_item_id) AS bal 
     ON bal.budget_item_id = bi.id 
ORDER BY bi.location 

Это занимает много времени. В таблицах budget_lines и balance_lines у меня более 5 000 000 строк в каждом.

Я также прилагаю EXPLAIN запроса, так что вы не сможете увидеть проблему. Все идентификаторы в каждой таблице индексируются. Есть ли какой-либо столбец, который, если бы был проиндексирован, вызвал запрос? Или, может быть, мне нужно изменить его.

*** LEFT JOIN необходимо, потому что мне нужно получить все элементы из nudget_items, даже если они не существуют в таблице balance/budget_line.

Схема: каждый бюджет имеет свои бюджетные рамки. У каждого баланса есть свои балансы. Запрос нацелен на то, чтобы таблица ОДНО суммировала различия между бюджетом и несколькими балансами.

enter image description here

Вы можете увидеть больше изображений здесь: http://i.stack.imgur.com/dlF8V.png

EDIT: После @Sebas ответов: enter image description here

Для @sabes голода, я ставлю здесь описательную: budget_items enter image description here

budget_lines enter image description here

balance_lines enter image description here

+0

_I также приложить EXPLAIN запроса ..._ (вы сделали?) – xQbert

+0

Просто сделал. Благодарю. –

+0

Ваши таблицы 'bal' и' bl', по-видимому, только суммируют значения для некоторого 'balance_id'. Вы должны добавить его в предложение where своих соответствующих подзапросов. – Sebas

ответ

0

Может быть что-то вроде этого; но без выборки данных и индексов, трудно увидеть

SELECT * 
FROM budget_items bi 
WHERE bi.location IS NOT NULL) AS bi 
INNER JOIN --Added inner for clarity -changed order I just like my inner's before my outers. 
    (SELECT budget_item_id, Sum(CASE WHEN balance_id = 12841 THEN coalesce(amount,0) END), 0) AS bal_amount1, 
          Sum(CASE WHEN balance_id = 18647 THEN coalesce(amount,0) END), 0) AS bal_amount2, 
          Sum(CASE WHEN balance_id = 18674 THEN coalesce(amount,0) END), 0) AS bal_amount3 
    FROM balance_lines 
    WHERE balance_ID in (12841, 18647, 18674) --This way balance_IDs which aren't in this list don't even get evaluated 
    GROUP BY budget_item_id) AS bal 
ON bal.budget_item_id = bi.id 
LEFT JOIN 
(SELECT budget_item_id, Sum(CASE WHEN budget_id = 21491 THEN coalesce(amount,0) END) AS bud_amount 
    FROM budget_lines 
    WHERE budget_Id = 21491 --Again since we only care about anything but budget_ID 21491, we can limit the results to JUST that 
    GROUP BY budget_item_id) AS bl 
ON bl.budget_item_id = bi.id 
+0

Отличается ли это от @Sabes? –

+0

только то, что я устранил IIF, сделав предположение, что вам действительно не нужно 0, когда 1 запись может быть NULL. – xQbert

+0

Я понимаю - Но я делаю –

Смежные вопросы