Search code examples
mysqlsqlgreatest-n-per-group

SQL - JOIN with MAX(created_at)


Problem

I have 3 tables: customers, companies and calls.

A customer has many Companies, and a Company has many calls. (both one to many).

The current status of a Company is the result of the last call for the company (MAX(created_at)).

Now I want a list of all companies for a customer with the columns of the last call in the results.

Needed Result

The result should be:
company.*, lastcall.*,

  • There could be calls with the same created_at date. Then there should be only 1 row in de result.
  • Not all companies has a call yet, the company should still be in the result and the columns of the call should be NULL. (left join)

Tables

customers
- id (int, primary key)
- name (varchar)
- address (varchar)
- city (varchar)

companies
- id (int, primary key)
- customer_id (int)
- name (varchar) - address (varchar)
- city (varchar)

calls
- id (int, primary key)
- company_id (int)
- result (varchar)
- created_at (datetime)

Attempt

A query which didn't work I came up with is:

SELECT * FROM companies co  
LEFT JOIN calls ca ON co.id = ca.company_id 
WHERE co.customer_id = ? 
GROUP BY co.id  
HAVING ca.created_at = (SELECT max(ll.created_at) FROM calls ll WHERE ll.company_id = co.id)  

Solution

  • It looks like I found the answer. This one gives the correct result, and still fast enough (0.27 seconds)

    SELECT co.*, v.* 
    FROM companies co 
    LEFT JOIN 
    ( 
        SELECT 
        ca.* 
        FROM calls ca 
        JOIN 
        ( 
            SELECT 
            company_id, 
            MAX(created_at) AS max_created_at 
            FROM calls 
            GROUP BY company_id 
        ) t 
        ON ca.company_id = t.company_id AND ca.created_at = t.max_created_at
        GROUP BY company_id
    ) v ON co.id = v.company_id
    

    Thanks everybody!