编写此查询的另一种方法

时间:2016-08-10 17:14:33

标签: mysql wamp

编写此查询的另一种方法是什么?

我的服务器需要花很多时间来执行这个:

SELECT c.id, c.franquicia_id, f.name, CONCAT(c.name,' ',c.surname) 
       contacto, c.created, DATE_FORMAT(c.created,'%d-%m-%Y') fecha 
FROM franquicias f, contacts c where f.id = c.franquicia_id 
 and c.created = (
                   select max(c2.created) 
                   from contacts c2 
                   WHERE c2.franquicia_id = c.franquicia_id
                 ) 
 and f.contract_id=2 
ORDER BY created DESC 
limit 10

3 个答案:

答案 0 :(得分:2)

此版本的子查询只需要为整个查询运行一次,而不是外部查询的每一行。

SELECT c.id, c.franquicia_id, f.name
   , CONCAT(c.name,' ',c.surname) AS contacto
   , c.created, DATE_FORMAT(c.created,'%d-%m-%Y') AS fecha 
FROM contacts AS c 
INNER JOIN franquicias AS f
   ON c.franquicia_id = f.id
    AND f.contract_id=2 
WHERE (c.franquicia_id, c.created) IN (
          SELECT franquicia_id, max(created) 
          FROM contacts
          GROUP BY franquicia_id
) 
ORDER BY created DESC 
LIMIT 10

或者,可以在子查询中使用子查询进行过滤。

f.contract_id=2可以放入ONWHERE;但是(并且优化器可以消除任何差异),将其保留在ON可能可能减少在where中检查的行,并使以后更容易将查询转换为{{1如果需要找到"最近没有f' of contract_id 2"。

注意:索引LEFT JOIN应该改进子查询,并使用(franquicia_id, created)来对付它;它还应该改善IN上的现有JOIN条件。

答案 1 :(得分:0)

引用此 Post

  

我个人认为INNER JOIN更好,因为它更多   可读。它表明了表格之间的关系。你得到了   在连接中的那些关系,并在WHERE中进行过滤   条款。这种分离使查询更具可读性。

SELECT 
    c.id, 
    c.franquicia_id, 
    f.name, 
    CONCAT(c.name,' ',c.surname) contacto, 
    c.created, 
    DATE_FORMAT(c.created,'%d-%m-%Y') fecha 
FROM franquicias f
INNER JOIN contacts c ON f.id = c.franquicia_id 
INNER JOIN 
(
    SELECT 
    C2.franquicia_id,
    MAX(C2.created) max_created
    FROM contacts C2 
    GROUP BY C2.franquicia_id
) AS maxCreatedForFrID
ON maxCreatedForFrID.franquicia_id = c.franquicia_id AND maxCreatedForFrID.max_created = c.created
WHERE f.contract_id = 2
ORDER BY created DESC
LIMIT 10;

注意:

franquicia_id,created表中的复合索引(contacts)可能会提高性能。

ALTER TABLE `contacts` ADD INDEX `idx_contacts_franquicia_id_created` (
    `franquicia_id`,
    `created`
);

答案 2 :(得分:0)

如果franquicias包含的记录不多,则下一个查询必须更有效:

SELECT c.id, c.franquicia_id, f.name, CONCAT(c.name,' ',c.surname) 
       contacto, c.created, DATE_FORMAT(c.created,'%d-%m-%Y') fecha 
FROM (
    SELECT DISTINCT MAX(c2.created) as c2_created, f2.*
    FROM contacts c2
    JOIN franquicias f2 ON f2.id = c2.franquicia_id
) f
JOIN contacts c ON f.id = c.franquicia_id
AND c.created = f.c2_created
WHERE f.contract_id=2 
ORDER BY created DESC 
limit 10