如何在mysql中提高查询效率

时间:2013-09-03 13:34:03

标签: 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  |
| ...    | ...  | ... | ...  | ...     | ...        | ...  |

我很乐意帮助改进查询,使其运行得更快,如果有其他方法可以获得所需的输出,我将非常感谢帮助。

谢谢。

1 个答案:

答案 0 :(得分: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以匹配示例数据中的命名。)