优化MySQL查询删除子查询

时间:2016-06-13 10:18:19

标签: mysql sql

有这些表格:

customers
---------------------
`id` smallint(5) unsigned NOT NULL auto_increment,
`name` varchar(100) collate utf8_unicode_ci default NOT NULL,
....

customers_subaccounts
-------------------------
`companies_id` mediumint(8) unsigned NOT NULL,
`customers_id` mediumint(8) unsigned NOT NULL,
`subaccount` int(10) unsigned NOT NULL

我需要让所有为同一家公司分配了多个子帐户的客户。

这就是我所拥有的:

SELECT * FROM customers 
WHERE id IN 
    (SELECT customers_id 
     FROM customers_subaccounts
     GROUP BY customers_id, companies_id 
     HAVING COUNT(subaccount) > 1)

但是这个查询太慢了。如果我将 DISTINCT 修饰符添加到子查询的SELECT中的 customers_id ,它最后会检索整个查询的相同客户列表,这样会更慢。也许有更好的方式没有subquerying,任何更快的东西都会有所帮助,而且我不确定它是否会检索到准确的正确列表。

任何帮助?

5 个答案:

答案 0 :(得分:4)

您可以使用INNER JOIN

替换子查询
SELECT t1.id
FROM customers t1
INNER JOIN
(
    SELECT DISTINCT customers_id 
    FROM customers_subaccounts
    GROUP BY customers_id, companies_id 
    HAVING COUNT(*) > 1
) t2
    ON t1.id = t2.customers_id

答案 1 :(得分:2)

您也可以尝试使用EXISTS(),这可能比加入更快:

SELECT * FROM customers t
WHERE EXISTS(SELECT 1 FROM customers_subaccounts s
             WHERE s.customers_id = t.id
             GROUP BY s.customers_id, s.companies_id 
             HAVING COUNT(subaccount) > 1)

您还应考虑添加以下索引(如果尚未存在):

customers_subaccounts (customers_id,companies_id,subaccount)
customers (id)

答案 2 :(得分:2)

假设你想为公司提供不同的子帐户(或者保证它们不同),那么在某些情况下,以下内容会更快:

select c.*
from (select distinct cs.customers_id
      from customers_subaccounts cs join
           customers_subaccounts cs2
           on cs.customers_id = cs2.customers_id and
              cs.companies_id = cs2.companies_id and
              cs.subaccount < cs2.subaccount
     ) cc join
     customers c
     on c.customers_id = cc.customers_id;

特别是,这可以利用customers_subaccounts(customers_id, companies_id, subaccount)上的索引。

注意:这假设subaccounts对于您想要的行是不同的。真正需要的是一种在customers_subaccounts表中定义唯一行的方法。

答案 3 :(得分:1)

尝试以下内容;)

SELECT DISTINCT t1.*
FROM customers t1
INNER JOIN customers_subaccounts t2 ON t1.id = t2.customers_id
GROUP BY t1.id, t1.name, t2.companies_id
HAVING COUNT(t2.subaccount) > 1

您也可以在index上添加customers_id

答案 4 :(得分:1)

有一种方法可以通过使用缓存子查询结果来加速查询。您的查询感知mysql的一个简单更改,可以缓存子查询结果:

SELECT * FROM customers 
WHERE id IN 
  (select * from
    (SELECT distinct customers_id 
     FROM customers_subaccounts
     GROUP BY customers_id, companies_id 
     HAVING COUNT(subaccount) > 1) t1);

我多年前就用它了,它对我很有帮助。