2013-02-01 141 views
1

我创建了一个查询,从两个表收集数据,summs起来,并表示案件的数量和总SUMM:创造一个更好的查询,总结两个表

SELECT 
    count(ut.id) AS total 
    , (SUM(internal_account) - SUM((SELECT 
      SUM(ub.bill_summs) 
     FROM 
      u_billing ub 
     WHERE 
      ub.bill_types = 'correction' 
      AND ub.contract_id = ut.contract_id 
    ))) AS summ 
FROM 
    u_transactions ut 
WHERE 
    ut.nulled = 0 
    AND ut.type = 'comission' 
    AND ut._status = 'not_paid' 
    AND DATE(ut.add_timestamp) = DATE('2012-05-11'); 

,但它实在是太慢了。在测试情况下,它给了这样的结果:

+-------+-------+ 
| total | summ | 
+-------+-------+ 
| 182 | 15105 | 
+-------+-------+ 
1 row in set (4.13 sec) 

这是182例,为仅为1天4.13秒,但我活的服务器有超过60万的情况下,所以这将是非常缓慢

任何想法,我如何重写查询以获得更好的性能?


解决方案与重塑查询(IES):

DELETE FROM tmpContractSums; 
INSERT INTO tmpContractSums 
SELECT 
    ub.contract_id 
    , SUM(ub.bill_summs) AS bill_summs 
FROM 
    u_billing ub 
WHERE 
    ub.bill_types = 'correction' 
GROUP BY ub.contract_id; 

SELECT 
    count(ut.id) AS total 
    , (SUM(internal_account) - SUM(bill_summs)) 
FROM 
    u_transactions ut 
LEFT JOIN tmpContractSums t ON ut.contract_id = t.contract_id 
WHERE 
    ut.nulled = 0 
    AND ut.type = 'comission' 
    AND ut._status = 'not_paid' 
    AND ut.add_timestamp BETWEEN '2012-05-11 00:00:00' AND '2012-05-11 23:59:59'; 

执行时间:500ms的

PS:既然不能放弃与WEBUSER表我刚刚创建的表:

CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0; 

我正在删除记录。速度不如下降,但仍然快于原始速度。

+0

你在其上运行一个查询分析器?你可以给我们一个关于'u_transactions'和'u_billing'的描述,例如计费是否有一个add_timestamp字段或任何其他加入账单和交易的字段? ...你有没有索引? – Nix

+1

您不可能加入u_billing ub和u_transactions ut表吗? – DevelopmentIsMyPassion

+0

@Nix允许合并它们的唯一参数是'contract_id'。是的,我尝试了索引,但没有任何改进。 – Peon

回答

1

如何简单地使用“临时”表?

DROP TABLE IF EXISTS tmpContractSums; 
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0; 
INSERT INTO tmpContractSums 
SELECT 
    ub.contract_id 
    SUM(ub.bill_summs) AS bill_summs 
FROM 
    u_billing ub 
WHERE 
    ub.bill_types = 'correction' 
GROUP BY ub.contract_id; 

SELECT 
    count(ut.id) AS total 
    , (SUM(internal_account) - COALESCE(bill_summs, 0)) 
FROM 
    u_transactions ut 
LEFT JOIN tmpContractSums t ON ut.contract_id = t.contract_id 
WHERE 
    ut.nulled = 0 
    AND ut.type = 'comission' 
    AND ut._status = 'not_paid' 
    AND ut.add_timestamp BETWEEN '2012-05-11' AND '2012-05-11 23:59:59'; 

这应该是更快,如果你愿意,你可以添加索引的“临时表”或使其与发动机的表格=记忆,如果你有足够的空间。

或者:

DROP TABLE IF EXISTS tmpContractSums; 
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0; 
INSERT INTO tmpContractSums 
SELECT 
    ub.contract_id 
    SUM(ub.bill_summs) AS bill_summs 
FROM 
    u_billing ub 
WHERE 
    ub.bill_types = 'correction' 
GROUP BY ub.contract_id; 

SELECT 
    count(ut.id) AS total 
    , (SUM(internal_account) - (SELECT bill_summs FROM tmpContractSums t WHERE ut.contract_id = t.contract_id)) 
FROM 
    u_transactions ut 
WHERE 
    ut.nulled = 0 
    AND ut.type = 'comission' 
    AND ut._status = 'not_paid' 
    AND ut.add_timestamp BETWEEN '2012-05-11' AND '2012-05-11 23:59:59'; 
+0

我不太了解这个解决方案。你能解释更多这是如何工作的吗?含义我没有看到表'tmpContractSums'的创建位置... – Peon

+0

它是由'INSERT INTO'自动创建的 – fancyPants

+0

那么为什么我会收到此消息? 'MySQL数据库错误:表'tmpcontractsums'不存在' – Peon

0

希望这有助于

SELECT 
     COUNT(A.id) AS total, 
     (SUM(A.internal_account) - SUM(COALESCE(B.bill_sums, 0)) AS 'Sum' 
    FROM 
    u_transactions A 
    LEFT JOIN u_billing B on A.contract_id = B.contract_id 
    WHERE 
    A.nulled = 0 AND 
    A.type = 'comission' AND 
    A._status = 'not_paid' AND 
    DATE(A.add_timestamp) = DATE('2012-05-11') 
    AND B.bill_types = 'correction'; 

编辑:

我没有注意到你的总结:子查询的结果

SELECT 
    count(ut.id) AS total 
    , (SUM(internal_account) - **SUM**((SELECT 
      **SUM**(ub.bill_summs) 
     FROM 
      u_billing ub 
     WHERE 
      ub.bill_types = 'correction' 
      AND ub.contract_id = ut.contract_id 
    ))) AS summ 
FROM 
    u_transactions ut 

也许你可以替换与COALESCE总和:

-COALESCE((SELECT 
     **SUM**(ub.bill_summs) 
    FROM 
     u_billing ub 
    WHERE 
     ub.bill_types = 'correction' 
     AND ub.contract_id = ut.contract_id 
),0) 
+0

这需要相同的时间并在最后给出错误的结果;)并非u_transactions中的所有合约都有“更正”数据。只有一些有。 – Peon

0

难道不是吗?我的意思是它必须工作得更好。

SELECT 
    count(ut.id) AS total 
    , SUM(internal_account - COALESCE(ub.b_summs, 0)) summ 
FROM u_transactions ut 
    LEFT JOIN 
     (
      SELECT 
       contract_id, 
       SUM(bill_summs) b_summs 
      FROM u_billing 
      WHERE bill_types = 'correction' 
      GROUP BY contract_id 
     ) AS ub 
     ON ub.contract_id = ut.contract_id 
WHERE 
    ut.nulled = 0 
    AND ut.type = 'comission' 
    AND ut._status = 'not_paid' 
    AND DATE(ut.add_timestamp) = DATE('2012-05-11'); 

此外,您必须避免使用WHERE子句应用于表列的函数。如果你有索引,使用函数不允许索引使用。使用这个来代替:

AND ut.add_timestamp >= DATE('2012-05-11') AND ut.add_timestamp < DATE('2012-05-12'); 
+0

'1行(10.29秒)'更慢: – Peon

+0

@DainisAbols OK。你试试我最后一条关于add_timestamp的建议吗? –

+0

只是一分钟,我正在测试:) – Peon

0

这应该加快速度:

SELECT 
    COUNT(ua.id) as total, 
    SUM(ua.internal_account - ua.corrections) as 'sum' 
FROM ( 
    SELECT 
     ut.id, 
     ut.internal_account, 
     SUM(COALESCE(ub.bill_sums, 0)) AS corrections 
    FROM 
     u_transactions ut 
      LEFT JOIN u_billing ub on ut.contract_id = ub.contract_id 
    WHERE 
     ut.nulled = 0 AND 
     ut.type = 'comission' AND 
     ut._status = 'not_paid' AND 
     DATE(ub.add_timestamp) = DATE('2012-05-11') AND 
     ut.bill_types = 'correction' 
    GROUP BY 
     ut.id 
    ) as ua 

编辑:修正add_timestamp表前缀插入和缺失GROUP BY

+0

Finally去测试它,它返回错误的结果,但执行速度更快;) – Peon

+0

@DainisAbols我在'add_timestamp'上放错了前缀。它现在能给出正确的结果吗? – Tony

+0

@DainisAbols Durrr,忘了放在GROUP BY中。现在它会很准确。虽然可能没有Tombom的答案那么快。 – Tony

相关问题