【问题标题】:SQL - JOIN with MAX(created_at)SQL - 加入 MAX(created_at)
【发布时间】:2015-01-31 08:08:44
【问题描述】:

问题

我有 3 个表:客户、公司和电话。

一个客户有很多公司,一个公司有很多电话。 (都是一对多)。

公司的当前状态是公司上次调用的结果 (MAX(created_at))。

现在我想要一个客户的所有公司列表,结果中包含最后一次通话的列。

需要的结果

结果应该是:
公司.*, lastcall.*,

  • 可能存在具有相同 created_at 日期的调用。那么结果中应该只有 1 行。
  • 并非所有公司都有电话,该公司仍应在结果中,电话的列应为 NULL。 (左连接)

表格

客户
- id(int,主键)
- 名称(varchar)
- 地址(varchar)
- 城市(varchar)

公司
- id(int,主键)
- customer_id (int)
- 名称(varchar) - 地址(varchar)
- 城市(varchar)

来电
- id(int,主键)
- company_id (int)
- 结果(varchar)
- created_at(日期时间)

尝试

我想出的一个没有用的查询是:

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)  

【问题讨论】:

    标签: mysql sql greatest-n-per-group


    【解决方案1】:

    您应该只加入一个选择,这样您就不会尝试重新评估该选择。

    SELECT co.id, co.label, ca.result, ca.id, t.date_created as most_recent
    FROM companies co
    LEFT JOIN
    (   SELECT MAX(created_at) as date_created, company_id
        FROM calls
        GROUP BY company_id
    ) t ON t.company_id = co.id
    JOIN calls ca ON ca.company_id = t.company_id AND t.date_created = ca.created_at
    WHERE co.customer_id = ?
    

    编辑:

    问题是您在最大日期每家公司有多个电话。要对此进行测试,只需拉出一个客户和公司并查看结果。

    SELECT co.id, co.label, ca.result, ca.id, ca.created_at as most_recent_date
    FROM companies co
    LEFT JOIN
    (   SELECT MAX(created_at) as date_created, company_id
        FROM calls
        GROUP BY company_id
    ) t ON t.company_id = co.id
    JOIN calls ca ON ca.company_id = t.company_id AND t.date_created = ca.created_at
    WHERE co.customer_id = ? AND co.id = ?
    

    运行此查询并指定特定公司。查看move_recent_date 列,查看每一行的日期是否相同,是否为最大日期

    【讨论】:

    • 这里不显示lastcall结果和lastcall id
    • @overflowed 现在可以了
    • result 和 id 不在聚合或 group by 子句中,这仍然不起作用
    • @overflowed 哎呀抱歉忘记加入通话。固定的。谢谢你的笔记
    • 您需要在左连接后加入呼叫,并且您需要将 t 表中的 max(created_at) 包含在呼叫表的连接中
    【解决方案2】:

    看来我找到了答案。 这个给出了正确的结果,并且仍然足够快(0.27 秒)

    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
    

    谢谢大家!

    【讨论】:

      【解决方案3】:

      您可以双重加入 lastcall 表,如下例所示:

      select companies.id, companies.name , lastcall.id, lastcall.result from companies
      inner join (select max(created_at) as lastcall, company_id from calls group by company_id) maxcalls 
      on (companies.id = maxcalls.company_id)
      inner join lastcall on (lastcall = created_at and companies.id = lastcall.company_id)
      where customer_id = ?
      
      
      select companies.* , ca.* from companies 
      inner join (select max(created_at) as lastcall, company_id from calls group by company_id) maxcalls on (companies.id = maxcalls.company_id)    
      inner join calls ca on (maxcalls.lastcall = ca.created_at and companies.id = ca.company_id)
      where customer_id = ?
      

      【讨论】:

        【解决方案4】:

        您可以通过两次加入calls 来做到这一点,第一次是在一个子查询中,您可以在其中检索每家公司的最后通话日期:

        SELECT * FROM companies co  
        LEFT JOIN (SELECT company_id, MAX(created_at) AS last_call FROM calls GROUP BY company_id) AS last_calls ON last_calls.company_id = co.id
        LEFT JOIN calls ca ON ca.company_id = last_calls.company_id AND ca.created_at = last_calls.last_call
        WHERE co.customer_id = ? 
        GROUP BY co.id
        

        【讨论】:

        • 您有语法错误 :) 该列是 created_at 而不是 last_call :) 仅供参考
        • 其实错误是写ca.create_at而不是ca.created_at。我无法测试它,因为我没有实际的数据库。它已修复。
        • 是的,这是正确的,我没有查看别名 :)
        • 这给出了正确的结果!性能只会差很多。 (90 秒)
        【解决方案5】:

        您应该进行子选择以从通话中创建最大值并将其用作公司和通话表的连接条件。

        SELECT
            co.id AS company_id,
            co.name AS company_name,
            ca.id AS lastcall_id,
            ca.result AS lastcall_result
        FROM companies AS co
        LEFT JOIN calls AS ca
            ON co.id = ca.company_id
        INNER JOIN
            (
                SELECT
                    company_id,
                    MAX(created_at) AS max_created_at
                FROM calls
                GROUP BY company_id
            ) AS max_created_per_company
            ON ca.company_id = max_created_per_company.company_id
            AND ca.created_at = max_created_per_company.created_at
        WHERE co.customer_id = ?
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-06
          • 2014-05-20
          • 1970-01-01
          • 2021-12-06
          • 1970-01-01
          • 2019-11-11
          相关资源
          最近更新 更多