Mysql OneToMany ПРИСЪЕДИНЕТЕ само към последния запис

Имам две таблици customers и тяхната contacts. Един клиент може да има много данни за контакт. В случай, че трябва да получа само последните добавени данни за контакт с клиентите. Мога да постигна това до subquery. Но когато данните са огромни, се сблъсквам с липса на производителност при заявките за всички данни на клиентите.

Таблица с клиенти (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    |                |
+-------------------+--------------+------+-----+---------+----------------+

Таблица с контакти (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);

Трябва да получа имената на компаниите на клиента и последния добавен телефонен номер за имената на всяка компания. Има ли някакъв оптимизиран начин или начин без използване на подзаявка, за да се постигне това?

Решен

Некорелираните подзаявки винаги дават по-добра производителност от корелираните подзаявки.


person Rajez    schedule 10.11.2017    source източник
comment
можете ли да обясните вашето запитване?   -  person rai    schedule 10.11.2017
comment
Трябва да получа имена на фирми на клиенти и техните телефонни номера. Само един телефонен номер за всеки клиент и това трябва да е последният добавен.   -  person Rajez    schedule 10.11.2017
comment
Отговорът на Бил Карвин може да ви помогне Retrieving the last record in each group   -  person M Khalid Junaid    schedule 10.11.2017
comment
@Rajez не, имам предвид да използвам синтаксиса за обяснение, таблицата може да не е оптимизирана и трябва да има индекс някъде   -  person rai    schedule 10.11.2017
comment
Оптимален максимум по групи   -  person Rick James    schedule 11.11.2017


Отговори (1)


Използвайте второ присъединяване към подзаявка, която идентифицира най-новия запис на контакт за всеки клиент:

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;

Това е модификация на първия ви опит за заявка. Обърнете внимание, че вашето условие за присъединяване е нарушено, защото всъщност не свързва правилно таблицата с клиенти и контакти. Основното присъединяване трябва да бъде customers_customers.id съвпадения с customers_customercontacts.customer_id. В допълнение към тази корекция правя допълнително присъединяване, за да огранича до най-новия запис на контакт за всеки клиент.

Една от причините, поради които този подход може да подобри производителността спрямо това, което сте имали първоначално, е, че тази заявка използва несвързана подзаявка, за да намери най-новия контакт за всеки клиент. Вашите първоначални опити използваха корелирани подзаявки, които обикновено не се представят добре.

person Tim Biegeleisen    schedule 10.11.2017
comment
Благодаря ти. Виждам добро подобрение в продължителността на заявката. Можете ли да обясните как тази промяна подобрява производителността? - person Rajez; 10.11.2017
comment
@Rajez добавих обяснение. - person Tim Biegeleisen; 11.11.2017