MySQL LEFT JOIN使用MAX&在连接表上的GROUP BY和获取与一列的MAX值对应的其他列?

时间:2017-07-14 18:48:45

标签: mysql sql

enter image description here

SELECT `a`.`id`, `a`.`ClientName`, b.id as ActivityId, max(b.DueDate) 
FROM `clients` as `a`
LEFT JOIN activities b on b.ClientId = a.id 
GROUP BY `a`.`id`

如何获得与MAX值对应的行? 这里我得到了正确的Max DueDate但是ActivityId与MAX DueDate行没有对应

链接到sqlfiddle

在这个演示exmaple链接中:这里max DueDate是2017-07-10它的正确。 ActivityId不正确。它显示为1,但它应显示2.请检查屏幕截图

2 个答案:

答案 0 :(得分:1)

我们假设这是你的clients表:

CREATE TABLE clients
(
    id INTEGER NOT NULL PRIMARY KEY,
    ClientName varchar(100) NOT NULL
) ;

INSERT INTO clients
VALUES
    (1, 'Client 1'),
    (2, 'Client 2') ;

这是你的activities

CREATE TABLE activities
(
   id INTEGER NOT NULL PRIMARY KEY,
   ClientId INTEGER NOT NULL REFERENCES client(id),
   DueDate DATE NOT NULL
) ;

INSERT INTO activities
VALUES
   (1, 1, '2017-01-01'),
   (2, 1, '2017-12-31'),
   (3, 1, '2017-05-05'),
   (4, 2, '2017-01-03'),
   (5, 2, '2017-03-04'),
   (6, 2, '2017-06-07') ;

(如果使用MySQL / MariaDB:我们确保我们GROUP BY使用SQL标准,以避免错误。如果使用PostgreSQL,省略它; PostgreSQL GROUP BY已经遵循SQL标准)

SET sql_mode = 'ONLY_FULL_GROUP_BY' ;

我们首先制作一个简单 GROUP BY来获取每个MAX(DueDate)的{​​{1}}:

ClientId

我们得到:

ClientId | MaxDate   
-------: | :---------
       1 | 2017-12-31
       2 | 2017-06-07

有了这个结果,我们将它包装为子查询(SELECT ClientId, max(DueDate) AS MaxDate FROM activities GROUP BY ClientId ; ),并将q0JOIN表包装起来,以检索相应的激活。 我们还activitesJOIN一起检索客户数据:

clients

我们得到:

ClientName | ClientId | ActivityId | DueDate   
:--------- | -------: | ---------: | :---------
Client 1   |        1 |          2 | 2017-12-31
Client 2   |        2 |          6 | 2017-06-07

您可以在 dbfiddle here

查看所有内容

注意:根据您的评论SELECT c.ClientName, q0.ClientId, a.id AS ActivityId, a.DueDate FROM (SELECT ClientId, max(DueDate) AS MaxDate FROM activities GROUP BY ClientId ) AS q0 JOIN activities a ON a.ClientId = q0.ClientId AND a.DueDate = q0.MaxDate RIGHT JOIN clients c ON c.id = q0.ClientId ORDER BY c.ClientName ; ,如果您需要所有客户,即使他们没有活动。 RIGHT JOIN只会为提供活动。

注意:这是SQL标准,不仅仅是MySQL或PostgreSQL。

警告:如果两个或更多活动恰好与JOIN一致,您将获得所有这些活动。

如果发生这种情况并且您只想一个,那么您可以在没有JOIN的情况下解决问题,但使用带有某个Max(DueDate)子查询(优先考虑如果有多个你真正想要的那个)和ORDER BY

答案 1 :(得分:0)

对于分组,您需要将select语句中的所有列分组为:

SELECT
  `a`.`id`,
  `a`.`ClientName`,
   b.id as ActivityId,
   b.DueDate
FROM `clients` as `a`
  LEFT JOIN activities b on b.ClientId = a.id
Where b.DueDate in (select max(DueDate) from activities)
GROUP BY `a`.`id`;