MySQL: Как сделать запрос между 2 таблицами, который возвращает значение NULL в строку, которой нет во 2-й таблице?

#mysql

Вопрос:

У меня есть эти 2 таблицы

1-я таблица «Пользователи»

  ---- ----------- ---------- 
| ID | FirstName | LastName |
 ---- ----------- ---------- 
| 1  | Jeff      | Bezos    |
| 2  | Bill      | Gates    |
| 3  | Elon      | Musk     |
 ---- ----------- ----------  
 

2-я Таблица «Рекорды»

  ---- -------- ------------ 
| ID | IDUser | RecordDate |
 ---- -------- ------------ 
| 1  | 1      | 15/06/2021 |
| 2  | 2      | 05/06/2021 |
| 3  | 2      | 12/06/2021 |
| 4  | 2      | 02/06/2021 |
| 5  | 1      | 17/06/2021 |
 ---- -------- ------------  
 

Таким образом, эти 2 таблицы связаны друг с другом с помощью записей ключа Foring.Лентяи -> Users.ID

Я хотел сделать запрос, который делает это

  ----------- ---------- ---------------- -------------------- 
| FirstName | LastName | Lastest Record | Numbers of Records |
 ----------- ---------- ---------------- -------------------- 
| Jeff      | Bezos    | 17/06/2021     | 2                  |
| Bill      | Gates    | 12/06/2021     | 3                  |
| Elon      | Musk     | NULL           | NULL               |
 ----------- ---------- ---------------- --------------------  
 

Ответ №1:

Вам нужно использовать LEFT JOIN для того, чтобы вернуть пользователей тоже без записей; затем функции MAX and COUNT aggregate.

Первая версия: Это вернет 0 количество записей вместо NULL , когда нет записей для конкретного пользователя. Последняя запись будет NULL такой, как и ожидалось.

 SELECT 
  FirstName,
  LastName,
  MAX(RecordDate) AS LatestRecord,
  COUNT(Records.ID) AS NumberOfRecords
FROM Users LEFT JOIN Records on Users.ID = Records.IDUser
GROUP BY Users.ID;
 

Если вы хотите NULL вместо 0 этого (чего обычно вы не хотите), вы можете использовать IF функцию следующим образом:

 SELECT 
  FirstName,
  LastName,
  MAX(RecordDate) AS LatestRecord,
  IF(COUNT(Records.ID) > 0, COUNT(Records.ID), NULL) AS NumberOfRecords
FROM Users LEFT JOIN Records on Users.ID = Records.IDUser
GROUP BY Users.ID;
 

Вторая версия: Может случиться так, что выполнение приведенного выше запроса вернет ошибку, что-то вроде:

Ошибка: ER_WRONG_FIELD_WITH_GROUP: …; это несовместимо с sql_mode=only_full_group_by

Это происходит, когда/если включен режим SQL ONLY_FULL_GROUP_BY (который используется по умолчанию с MySQL 5.7.5). Чтобы обойти эту ошибку, вы можете использовать ANY_VALUE функцию для выбора неагрегированных полей:

 SELECT 
  ANY_VALUE(FirstName) AS FirstName,
  ANY_VALUE(LastName) AS LastName,
  MAX(RecordDate) AS LatestRecord,
  COUNT(Records.ID) AS NumberOfRecords
FROM Users LEFT JOIN Records on Users.ID = Records.IDUser
GROUP BY Users.ID;
 

Ответ №2:

левое соединение выберите всех пользователей, даже если у них нет записей

 select * from users left join records on records.IDUser = ID;