编写此查询的另一种方法
Another way to write this query
编写此查询的另一种方法是什么?
我的服务器执行这个需要很多时间:
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
这个版本的子查询只需要 运行 整个查询一次,而不是外部查询的每一行。
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
或者,子查询可以在附加的 JOIN 中使用以进行过滤。
f.contract_id=2
可以放在 ON
或 WHERE
中;但是(并且优化器可能会消除任何差异),将其保留在 ON
中可能 可能 减少在 where 中检查的行,并使以后更容易将查询转换为LEFT JOIN
如果需要查找 "most recent contacts with no f's of contract_id 2"。
注意:索引 (franquicia_id, created)
应该改进子查询,而 IN
用于它;它还应该改进 franquicia_id
.
上的现有 JOIN 条件
引自此Post
I personally think the INNER JOIN is better, because it is more
readable. It shows better the relations between the table. You got
those relations in the join, and you do the filtering in the WHERE
clause. This separation makes the query more readable.
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;
注:
contacts
table 中的复合索引 (franquicia_id,created
) 可能会提高性能。
ALTER TABLE `contacts` ADD INDEX `idx_contacts_franquicia_id_created` (
`franquicia_id`,
`created`
);
如果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
编写此查询的另一种方法是什么?
我的服务器执行这个需要很多时间:
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
这个版本的子查询只需要 运行 整个查询一次,而不是外部查询的每一行。
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
或者,子查询可以在附加的 JOIN 中使用以进行过滤。
f.contract_id=2
可以放在 ON
或 WHERE
中;但是(并且优化器可能会消除任何差异),将其保留在 ON
中可能 可能 减少在 where 中检查的行,并使以后更容易将查询转换为LEFT JOIN
如果需要查找 "most recent contacts with no f's of contract_id 2"。
注意:索引 (franquicia_id, created)
应该改进子查询,而 IN
用于它;它还应该改进 franquicia_id
.
引自此Post
I personally think the INNER JOIN is better, because it is more readable. It shows better the relations between the table. You got those relations in the join, and you do the filtering in the WHERE clause. This separation makes the query more readable.
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;
注:
contacts
table 中的复合索引 (franquicia_id,created
) 可能会提高性能。
ALTER TABLE `contacts` ADD INDEX `idx_contacts_franquicia_id_created` (
`franquicia_id`,
`created`
);
如果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