MySQL上的MySQL加入

我有两个我想要加入的My SQL表,它们被简化为:

+----------------------------+
| customers                  |
+-------------+-------+------+
| customer_id | first | last |
+-------------+-------+------+
| 0           | John  | Doe  |
+-------------+-------+------+
| 1           | Jane  | Doe  |
+-------------+-------+------+

+-------------------------------------------------------------------+
| contact_log                                                       |
+----------------+-------------+--------------+---------------------+
| contact_log_id | customer_id | contact_type | date_time           |
+----------------+-------------+--------------+---------------------+
| 0              | 0           | email        | 2016-05-17 03:21:45 |
+----------------+-------------+--------------+---------------------+
| 1              | 0           | phone        | 2016-05-17 16:11:35 |
+----------------+-------------+--------------+---------------------+
| ...            | ...         | ...          |                     |
+----------------+-------------+--------------+---------------------+

我需要一个查询来选择客户,以及他们最近的联系时间和类型.我试过这个查询:

SELECT
    `customers`.`customer_id`,
    `customers`.`first`,
    `customers.last`,
    `contact_log`.`contact_type`,
    MAX(`contact_log`.`date_time`)
FROM
    `customers`
JOIN
    `contact_log`
ON
    `customers`.`customer_id` = `contact_log`.`customer_id`

这通常会错误地对date_time进行排序.在研究该问题时,某些MySQL版本中存在一个错误,其中MAX和MIN无法与DATETIME一起正常工作.所以解决方法是

MAX(CAST(`contact_log`.`date_time` AS CHAR))

那么我得到客户行,最新的date_time.但是,contact_type与时间不匹配.在示例数据中,我的结果如下所示:

+-------------+-------+------+--------------+---------------------+
| customer_id | first | last | contact_type | date_time           |
+-------------+-------+------+--------------+---------------------+
| 0           | John  | Doe  | email        | 2016-05-17 16:11:35 |
+-------------+-------+------+--------------+---------------------+

contact_type与contact_log表中的date_time不匹配.我怀疑这与SELECT / JOIN发生的顺序以及何时被过滤有关.我必须小心子查询(避免n 1),因为这些是非常大的表,并且可能从两个表中选择数百行.

使contact_type和date_time匹配的正确查询是什么?

更新
当我最初问这个问题时,我没有意识到你不能在视图中进行子查询.这需要保存为视图.为了完整解决这个问题,如何将其分解为多个视图并将其合并为一个视图?

最佳答案 没有意见

一个简单的解决方案是使用子查询来获取按日期排序的联系日志,由全局查询调用以按customer_id对它们进行分组:

SELECT * FROM
(
    SELECT
        customers.customer_id,
        customers.first,
        customers.last,
        contact_log.contact_type,
        contact_log.date_time

        FROM customers
            INNER JOIN contact_log ON contact_log.customer_id = customers.customer_id -- or LEFT JOIN - see comment

        ORDER BY contact_log.date_time DESC
) logs GROUP BY logs.customer_id

如果你有一个庞大的数据库,你将不得不检查架构是否正确索引,缓存启用等…

有意见

逻辑是一样的.子查询由第一个视图替换,第一个视图由“全局”视图请求以对结果进行分组.请注意,我在“logs”视图中使用GROUP BY而不是ORDER BY.

CREATE VIEW logs AS 
    SELECT
        customers.customer_id,
        customers.first,
        customers.last,
        contact_log.contact_type,
        contact_log.date_time

        FROM customers
            LEFT JOIN contact_log ON contact_log.customer_id = customers.customer_id

        GROUP BY
            customers.customer_id,
            contact_log.date_time DESC,
            contact_log.contact_type DESC;

CREATE VIEW testview AS SELECT * FROM logs GROUP BY logs.customer_id;

SELECT * FROM testview;
点赞