MySQL 查询以从子表中获取最新值
MySQL query to get latest value from child tables
我有一个 table 的客户和三个 table 的相关细节,从这个 Fiddle。
我想做的是获取最新联系日期的客户数据及其相关行。
我想根据该查询创建一个视图并能够按操作员 ID 进行过滤。我得到的行数总是不符合我的预期。
以下是我的查询,有人可以帮我弄清楚为什么 returns 结果不正确吗?
select c.*,cs.client_status,cn.client_note,cd.contact_date from clienti c
left join client_status cs on c.id = cs.client
left join client_notes cn on c.id = cn.client
left join client_contact_date cd on c.id = cd.client
where
(
(
`cd`.`contact_date` = (select max(`client_contact_date`.`contact_date`) from `client_contact_date` where `client_contact_date`.`client` = `c`.`id`)
)
AND
(
`cn`.`mod_time` = (select max(`client_notes`.`mod_time`) from `client_notes` where `client_notes`.`client` = `c`.`id`)
)
AND
(
`cs`.`mod_time` = (select max(`client_status`.`mod_time`) from `client_status` where `client_status`.`client` = `c`.`id`)
)
)
我建议您将其分解成更小的部分,然后开始将它们连接在一起。
您想要的一切的核心是每个客户的最新 contact_date/status/note。您可以使用聚合获得每个:
SELECT client, MAX(contact_date) AS latestContact
FROM client_contact_date
GROUP BY client;
SELECT client, MAX(mod_time) AS latestNote
FROM client_notes
GROUP BY client;
SELECT client, MAX(mod_time) AS latestStatus
FROM client_status
GROUP BY client;
第一个查询可以很容易地外连接到客户端 table 以获取客户端信息,因为每个客户端应该只有一行。对于这些子查询中的最后两个,您必须重新连接到原始 tables(注释、状态)以获取这样的信息,因为该行也必须按时间匹配:
SELECT n.client, n.client_note, n.mod_time
FROM client_notes n
JOIN(
SELECT client, MAX(mod_time) AS latestNote
FROM client_notes
GROUP BY client) t ON t.client = n.client AND t.latestNote = n.mod_time;
SELECT s.client, s.client_status, s.mod_time
FROM client_status s
JOIN(
SELECT client, MAX(mod_time) AS latestStatus
FROM client_status
GROUP BY client) t ON t.client = s.client AND t.latestStatus = s.mod_time;
一旦你拥有所有这些东西,你就可以使用外连接将最新的信息行放在一起:
SELECT c.id, c.clientName, c.operators, cd.latestContact, cn.client_note, cn.latestNote, cs.client_status, cs.latestStatus
FROM clienti c
LEFT JOIN(
SELECT client, MAX(contact_date) AS latestContact
FROM client_contact_date
GROUP BY client) cd ON cd.client = c.id
LEFT JOIN(
SELECT n.client, n.client_note, n.mod_time AS latestNote
FROM client_notes n
JOIN(
SELECT client, MAX(mod_time) AS latestNote
FROM client_notes
GROUP BY client) t ON t.client = n.client AND t.latestNote = n.mod_time) cn ON cn.client = c.id
LEFT JOIN(
SELECT s.client, s.client_status, s.mod_time AS latestStatus
FROM client_status s
JOIN(
SELECT client, MAX(mod_time) AS latestStatus
FROM client_status
GROUP BY client) t ON t.client = s.client AND t.latestStatus = s.mod_time) cs ON cs.client = c.id;
不过我想发表一个评论。我看到您将运算符存储为列表。这破坏了规范化,通常是一个非常糟糕的主意。有关我的信息,请参阅 Is storing a delimited list in a database column really that bad?
这是我的查询的 SQL Fiddle 示例。
我有一个 table 的客户和三个 table 的相关细节,从这个 Fiddle。
我想做的是获取最新联系日期的客户数据及其相关行。
我想根据该查询创建一个视图并能够按操作员 ID 进行过滤。我得到的行数总是不符合我的预期。
以下是我的查询,有人可以帮我弄清楚为什么 returns 结果不正确吗?
select c.*,cs.client_status,cn.client_note,cd.contact_date from clienti c
left join client_status cs on c.id = cs.client
left join client_notes cn on c.id = cn.client
left join client_contact_date cd on c.id = cd.client
where
(
(
`cd`.`contact_date` = (select max(`client_contact_date`.`contact_date`) from `client_contact_date` where `client_contact_date`.`client` = `c`.`id`)
)
AND
(
`cn`.`mod_time` = (select max(`client_notes`.`mod_time`) from `client_notes` where `client_notes`.`client` = `c`.`id`)
)
AND
(
`cs`.`mod_time` = (select max(`client_status`.`mod_time`) from `client_status` where `client_status`.`client` = `c`.`id`)
)
)
我建议您将其分解成更小的部分,然后开始将它们连接在一起。
您想要的一切的核心是每个客户的最新 contact_date/status/note。您可以使用聚合获得每个:
SELECT client, MAX(contact_date) AS latestContact
FROM client_contact_date
GROUP BY client;
SELECT client, MAX(mod_time) AS latestNote
FROM client_notes
GROUP BY client;
SELECT client, MAX(mod_time) AS latestStatus
FROM client_status
GROUP BY client;
第一个查询可以很容易地外连接到客户端 table 以获取客户端信息,因为每个客户端应该只有一行。对于这些子查询中的最后两个,您必须重新连接到原始 tables(注释、状态)以获取这样的信息,因为该行也必须按时间匹配:
SELECT n.client, n.client_note, n.mod_time
FROM client_notes n
JOIN(
SELECT client, MAX(mod_time) AS latestNote
FROM client_notes
GROUP BY client) t ON t.client = n.client AND t.latestNote = n.mod_time;
SELECT s.client, s.client_status, s.mod_time
FROM client_status s
JOIN(
SELECT client, MAX(mod_time) AS latestStatus
FROM client_status
GROUP BY client) t ON t.client = s.client AND t.latestStatus = s.mod_time;
一旦你拥有所有这些东西,你就可以使用外连接将最新的信息行放在一起:
SELECT c.id, c.clientName, c.operators, cd.latestContact, cn.client_note, cn.latestNote, cs.client_status, cs.latestStatus
FROM clienti c
LEFT JOIN(
SELECT client, MAX(contact_date) AS latestContact
FROM client_contact_date
GROUP BY client) cd ON cd.client = c.id
LEFT JOIN(
SELECT n.client, n.client_note, n.mod_time AS latestNote
FROM client_notes n
JOIN(
SELECT client, MAX(mod_time) AS latestNote
FROM client_notes
GROUP BY client) t ON t.client = n.client AND t.latestNote = n.mod_time) cn ON cn.client = c.id
LEFT JOIN(
SELECT s.client, s.client_status, s.mod_time AS latestStatus
FROM client_status s
JOIN(
SELECT client, MAX(mod_time) AS latestStatus
FROM client_status
GROUP BY client) t ON t.client = s.client AND t.latestStatus = s.mod_time) cs ON cs.client = c.id;
不过我想发表一个评论。我看到您将运算符存储为列表。这破坏了规范化,通常是一个非常糟糕的主意。有关我的信息,请参阅 Is storing a delimited list in a database column really that bad?
这是我的查询的 SQL Fiddle 示例。