查询花费了太多时间

时间:2013-07-13 09:33:57

标签: mysql sql

我想就下面的问题采取您的想法:

select a.expense_code, a.expense_date, a.expense_supplier_code, b.supplier_name, a.expense_discount, a.expense_payment_method, a.expense_payment_transfer_to, a.expense_advance, a.expense_status,
                            sum(c.expense_item_buy_price * c.expense_item_quantity) , d.account_name, a.expense_counter, a.expense_type, a.expense_saving_type, a.expense_payment_transfer_from
                            from expense_data a, supplier_data b, expense_item c, tree_data d
                            where a.expense_supplier_code = b.supplier_code and a.expense_payment_transfer_to= d.account_code
                            and a.expense_counter = c.expense_counter
                            and a.expense_date between '2013-01-01' and '2014-01-01' and a.expense_status = 0 or a.expense_status = 2 group by (a.expense_counter);

即使在expense_data表中,也有四个索引:

,此查询花费了很多时间
1- Expense_code. 
2- expense_user_id
3- expense_supplier_code
4- expense_payment_transfer_from

我不知道为什么需要这么多时间因为两次加入或是因为太多的不足。你能建议吗?

4 个答案:

答案 0 :(得分:2)

可能是你的where子句包含逻辑错误。 查看最后一行(最后一个OR条件):

where 
  ....
  and a.expense_counter = c.expense_counter 
  and a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
  and a.expense_status = 0 
  or a.expense_status = 2 

这意味着“在日期等之间记录并且状态为0,或者记录状态为2的所有记录

答案 1 :(得分:0)

为了加快速度,您可能希望尝试在您加入的列的组合上创建组合索引。该索引可能比您现在拥有的四个独立索引更有用,尽管您仍然可以保留这些索引。除了这四个字段之外,您甚至可以通过向索引添加status和/或expense_data进行试验。

答案 2 :(得分:0)

重新编码以使连接更清晰(并删除那个大规模连接,如果费用状态是所有表都已加入),则给出: -

SELECT a.expense_code, 
    a.expense_date, 
    a.expense_supplier_code, 
    b.supplier_name, 
    a.expense_discount, 
    a.expense_payment_method, 
    a.expense_payment_transfer_to, 
    a.expense_advance, 
    a.expense_status,
    SUM(c.expense_item_buy_price * c.expense_item_quantity) , 
    d.account_name, 
    a.expense_counter, 
    a.expense_type, 
    a.expense_saving_type, 
    a.expense_payment_transfer_from
FROM expense_data a, 
INNER JOIN supplier_data b ON a.expense_supplier_code = b.supplier_code
INNER JOIN expense_item c ON a.expense_counter = c.expense_counter
INNER JOIN tree_data d ON a.expense_payment_transfer_to= d.account_code
WHERE a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
AND a.expense_status = 0 OR a.expense_status = 2 
GROUP BY (a.expense_counter);

请注意,在supplier_data表上有一个关于supplier_code的索引,在expense_item表上有一个关于expense_counter的索引,在tree_data表上关于account_code的索引是很重要的。

我怀疑你真的不希望退回费用状态为0且费用日期在该范围内的项目,任何费用状态记录2都与日期无关,因此以下内容可能是您想要的: -

SELECT a.expense_code, 
    a.expense_date, 
    a.expense_supplier_code, 
    b.supplier_name, 
    a.expense_discount, 
    a.expense_payment_method, 
    a.expense_payment_transfer_to, 
    a.expense_advance, 
    a.expense_status,
    SUM(c.expense_item_buy_price * c.expense_item_quantity) , 
    d.account_name, 
    a.expense_counter, 
    a.expense_type, 
    a.expense_saving_type, 
    a.expense_payment_transfer_from
FROM expense_data a, 
INNER JOIN supplier_data b ON a.expense_supplier_code = b.supplier_code
INNER JOIN expense_item c ON a.expense_counter = c.expense_counter
INNER JOIN tree_data d ON a.expense_payment_transfer_to= d.account_code
WHERE a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
AND a.expense_status IN (0, 2)
GROUP BY (a.expense_counter);

答案 3 :(得分:-1)

您必须将OR条件放在括号中:

SELECT a.expense_code, 
   a.expense_date, 
   a.expense_supplier_code, 
   b.supplier_name, 
   a.expense_discount, 
   a.expense_payment_method, 
   a.expense_payment_transfer_to, 
   a.expense_advance, 
   a.expense_status, 
   SUM(c.expense_item_buy_price * c.expense_item_quantity), 
   d.account_name, 
   a.expense_counter, 
   a.expense_type, 
   a.expense_saving_type, 
   a.expense_payment_transfer_from 
FROM expense_data a, 
   supplier_data b, 
   expense_item c, 
   tree_data d 
WHERE a.expense_supplier_code = b.supplier_code 
   AND a.expense_payment_transfer_to = d.account_code 
   AND a.expense_counter = c.expense_counter 
   AND a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
   AND (a.expense_status = 0 OR a.expense_status = 2)
GROUP BY a.expense_counter;