Mysql OneToMany JOIN 仅最近的记录

Mysql OneToMany JOIN most recent record only

我有两个表 customers 和它们的 contacts。一个客户可以有很多联系方式。在某些情况下,我只需要获取 customers.I 的最后添加的联系方式,可以通过 subquery 获得。但是当数据很大时,我面临着查询所有客户数据时性能不足的问题。

Customer table (customers_customers)

+-------------------+--------------+------+-----+---------+----------------+
| Field             | Type         | Null | Key | Default | Extra          |
+-------------------+--------------+------+-----+---------+----------------+
| id                | int(11)      | NO   | PRI | NULL    | auto_increment |
| company_name      | varchar(150) | NO   |     | NULL    |                |
| logo              | varchar(100) | NO   |     | NULL    |                |
+-------------------+--------------+------+-----+---------+----------------+

Contacts table (customers_customercontacts)

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| email       | varchar(100) | YES  |     | NULL    |                |
| mobile      | varchar(50)  | YES  |     | NULL    |                |
| customer_id | int(11)      | NO   | MUL | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

我尝试了以下查询,得到了结果,但查询速度很慢。

SELECT
    c.id,
    c.company_name,
    d.mobile
FROM customers_customers AS c
LEFT JOIN customers_customercontacts AS d
    ON d.id = (SELECT MAX(id) FROM customers_customercontacts WHERE d.customer_id = d.id);

SELECT
    c.id,
    c.company_name,
    d.mobile
FROM customers_customers AS c
LEFT JOIN customers_customercontacts AS d
    ON d.id = (SELECT id FROM customers_customercontacts WHERE d.customer_id = d.id
               ORDER BY id DESC LIMIT 1);

我需要获取客户的 company_names 和每个 company_names 的最后添加的 phone_number。 是否有任何优化的方式或不使用子查询的方式来实现这一点?

Solved

非相关子查询的性能总是优于相关子查询。

使用第二个连接到子查询,该子查询标识每个客户的最新联系人记录:

SELECT
    c.id,
    c.company_name,
    d1.mobile
FROM customers_customers AS c
LEFT JOIN customers_customercontacts AS d1
    ON c.id = d1.customer_id
INNER JOIN
(
    SELECT customer_id, MAX(id) AS max_id
    FROM customers_customercontacts
    GROUP BY customer_id
) AS d2
    ON d1.customer_id = d2.customer_id AND
       d1.id = d2.max_id;

这是对您的第一次查询尝试的修改。请注意,您的加入条件已损坏,因为它并未真正正确关联客户和联系人 table。基本连接应该是 customers_customers.id 匹配到 customers_customercontacts.customer_id。在此更正之上,我进行了额外的连接以限制每个客户的最新联系人记录。

此方法可能会比您最初使用的方法提高性能的一个原因是此查询使用非相关子查询来查找每个客户的最新联系人。您最初的尝试使用了往往性能不佳的相关子查询。