我有两个我想要加入的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;