2013-09-03 4 views
3

Senario: Я работаю с двумя таблицами (структура ниже)Как я могу улучшить запрос для эффективности в MySQL

expenses_tb   person_expenses_tb 
+----+-----------+  +----+------+-------------+-----------+--------+ 
| id | expenses |  | id | year | expenses_id | person | amount | 
+----+-----------+  +----+------+-------------+-----------+--------+ 
| 1 | Bus  |  | 1 | 2007 | 1   | Will  | 20  | 
| 2 | Food  |  | 2 | 2007 | 2   | Will  | 200 | 
| 3 | Clothes |  | 3 | 2007 | 4   | Will  | 1000 | 
| 4 | Girlfriend|  | 4 | 2007 | 5   | Will  | 20  | 
| 5 | Taxi  |  | 5 | 2008 | 3   | Will  | 500 | 
+----+-----------+  | 6 | 2008 | 5   | Will  | 100 | 
         | 7 | 2008 | 2   | Holly  | 200 | 
         | 8 | 2007 | 5   | Holly  | 850 | 
         | .. | 2013 | ...   | ....  | ... | 

Я попробовал два разных запросов.

SELECT person, expenses, 
CASE expense_id WHEN 1 THEN amount END AS 'bus', 
CASE expense_id WHEN 2 THEN amount END AS 'food', 
CASE expense_id WHEN 3 THEN amount END AS 'clothes', 
CASE expense_id WHEN 4 THEN amount END AS girlfriend', 
CASE expense_id WHEN 5 THEN amount END AS 'taxi' 
FROM person_expenses_tb p 
JOIN expenses e ON e.id=p.expenses_id 
WHERE p.year = 2008 
GROUP BY p.person 

Запрос выше работает быстро, но не дает желаемого результата.

Второй запрос я попытался было

SELECT person, expenses, 
(SELECT amount FROM person_expenses_tb p_bus WHERE expense_id = 1 AND p_bus.person = p.person AND year=2008) AS 'bus', 
(SELECT amount FROM person_expenses_tb p_bus WHERE expense_id = 2 AND p_bus.person = p.person AND year=2008) AS 'food', 
(SELECT amount FROM person_expenses_tb p_bus WHERE expense_id = 3 AND p_bus.person = p.person AND year=2008) AS 'clothes', 
(SELECT amount FROM person_expenses_tb p_bus WHERE expense_id = 4 AND p_bus.person = p.person AND year=2008) AS girlfriend', 
(SELECT amount FROM person_expenses_tb p_bus WHERE expense_id = 5 AND p_bus.person = p.person AND year=2008) AS 'taxi' 
FROM person_expenses_tb p 
JOIN expenses e ON e.id=p.expenses_id 
WHERE p.year = 2008 
GROUP BY p.person 

этот запрос производится правильный результат, но его очень медленно, когда [person_expenses_tb] имеет более 2000 записей.

желаемый результат за 2007 год: у меня есть запрос на запрашиваемый год.

+--------+------+-----+------+---------+------------+------+ 
| person | Year | Bus | Food | Clothes | Girlfriend | Taxi | 
+--------+------+-----+------+---------+------------+------+ 
| Will | 2007 | 20 | 20 | 0  | 1000  | 20 | 
| Holly | 2007 | 0 | 0 | 0  | 0   | 850 | 
| ... | ... | ... | ... | ...  | ...  | ... | 

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

спасибо.

+0

У вас есть ключ или индекс на 'person_expenses_tb.expenses_id' и ПКС обоего таблиц? ключевой поиск не должен занимать много времени. – NDM

ответ

0

Первый запрос - правильный подход (в общем). Вам просто нужны функции агрегирования:

SELECT person, 
     sum(CASE p.expenses_id WHEN 1 THEN amount END) AS bus, 
     sum(CASE p.expenses_id WHEN 2 THEN amount END) AS food, 
     sum(CASE p.expenses_id WHEN 3 THEN amount END) AS clothes, 
     sum(CASE p.expenses_id WHEN 4 THEN amount END) AS girlfriend, 
     sum(CASE p.expenses_id WHEN 5 THEN amount END) AS taxi 
FROM person_expenses_tb p 
WHERE p.year = 2008 
GROUP BY p.person; 

Ваша версия не работает из-за «функции» MySQL. p.expenses_id не содержится в статье group by. В этом случае MySQL выбирает произвольное значение. Следовательно, будет заполнен только один из столбцов. Функция агрегации устраняет эту проблему.

Поскольку вы используете expense_id для поворота, вам не требуется соединение в справочной таблице. Я также удалил одинарные кавычки из имен столбцов. Хотя MySQL позволяет это, это плохая практика. Просто используйте одинарные кавычки для строковых констант. Если вам нужно избежать имени, используйте обратные кавычки или двойные кавычки.

(Я также изменил expense_id к expenses_id, чтобы соответствовать именованию в данном образце.)

+0

Интересно, можем ли мы включить 'cost_tb' там как-то ;-) – Strawberry

+0

Большое спасибо. Это было трюк! ... потрясающе !! – Govnah

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