MySQL查询从子表中获取最新值

时间:2015-07-21 15:24:16

标签: mysql subquery

我有一个客户表和三个相关详细信息表,如Fiddle所示。

我想要的是获取最新联系日期的客户数据及其相关行。

我想从该查询创建一个视图,并能够按运算符ID进行过滤。我总是得到一个错误的行数达到我的期望。

以下是我的查询,有人可以帮我弄清楚为什么会返回不正确的结果吗?

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`)
    )
)

1 个答案:

答案 0 :(得分:2)

我建议你把它分成小块,然后开始把连接放在一起。

您想要的所有内容的核心是每个客户的最新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;

第一个查询可以很容易地外部连接到客户端表以获取客户端信息,因为每个客户端应该只有一行。对于最后两个子查询,您必须联接回原始表(注释,状态)以获取这样的信息,因为该行也必须按时间匹配:

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示例。