left join in mysql后如何获取每个寄存器的最高日期?

How to get the highest date for each register after left join in mysql?

我在 mysql 中有两个表(用户和日志)。

USER TABLE

id     email            name      status
--    -------          ------    --------
1     "x@domain.com"   "Carlos"     1
2     "c@domain.com"   "Marie"      1
3     "k@domain.com"   "Jason"      1



LOG TABLE

id      time                    user_id      
--     -------                  -------
123    "2020-09-07 08:05:03"      1
124    "2020-09-07 08:32:21"      2
125    "2020-09-09 09:01:46"      1
126    "2020-09-07 11:05:03"      3

我想获取所有用户及其最后一次登录。然后,我有这个查询:

SELECT 
      user.id,
      user.name,
      user.email,
      MAX(log.time) as time
FROM user 
LEFT JOIN log on user.id = log.user_id
WHERE user.status_id = 1 
GROUP BY user.id 
ORDER BY log.time DESC

查询returns所有用户及其日志(如果没有该用户的日志则为null)但该日志不是该用户的最后一个。有人可以帮助我吗?

提前致谢。

如果您使用的是 MySQL 8+,那么 ROW_NUMBER 是一种明智的做法:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY time DESC) rn
    FROM log
)

SELECT 
    u.id,
    u.name,
    u.email,
    t.time
FROM user u
LEFT JOIN cte t ON u.id = t.user_id
WHERE
    u.status = 1 AND t.rn = 1
ORDER BY
    t.time DESC;
SELECT u.*, l.*
FROM user
JOIN log ON user.id = log.user_id
JOIN ( SELECT user_id, MAX(time) time
       FROM log
       GROUP BY user_id ) log1 ON log.user_id = log1.user_id AND log.time = log1.time

适用于MySQL5.x

您只需进行很少的更改即可使查询正常工作(除了两个拼写错误 - 额外的逗号和状态与 status_id):

order by 子句没有任何意义,因为结果集没有 log.time 字段,它只有 max(log.time),所以你需要排序,不需要使用 CTE 或子查询 - 只要您不想包含来自 log table:

的额外列

架构(MySQL v5.7)

CREATE TABLE `user` (
  `id` INTEGER primary key,
  `email` VARCHAR(14),
  `name` VARCHAR(8),
  `status` INTEGER
);

INSERT INTO `user`
  (`id`, `email`, `name`, `status`)
VALUES
  ('1', 'x@domain.com', 'Carlos', '1'),
  ('2', 'c@domain.com', 'Marie', '1'),
  ('3', 'k@domain.com', 'Jason', '1');

CREATE TABLE log (
  `id` INTEGER,
  `time` VARCHAR(21),
  `user_id` INTEGER
);

INSERT INTO log
  (`id`, `time`, `user_id`)
VALUES
  ('123', '2020-09-07 08:05:03', '1'),
  ('124', '2020-09-07 08:32:21', '2'),
  ('125', '2020-09-09 09:01:46', '1'),
  ('126', '2020-09-07 11:05:03', '3');

查询#1

SELECT 
      user.id,
      user.name,
      user.email,
      MAX(log.time) as time
FROM user 
LEFT JOIN log on user.id = log.user_id
WHERE user.status = 1 
GROUP BY user.id 
ORDER BY max(log.time) DESC;

结果:

| id  | name   | email        | time                |
| --- | ------ | ------------ | ------------------- |
| 1   | Carlos | x@domain.com | 2020-09-09 09:01:46 |
| 3   | Jason  | k@domain.com | 2020-09-07 11:05:03 |
| 2   | Marie  | c@domain.com | 2020-09-07 08:32:21 |