Соединение MySQL с суммой дат, сгруппированной по StudentNumber, хочет возвращать значение, даже если результат соединения строк равен 0

#mysql #date #sum

#mysql #Дата #сумма

Вопрос:

Как мне заставить студентов без результатов (совпадений) также отображать 0 TotalHours в этом запросе.

Добавлен реальный пример того, что мне требуется в dbfiddle и ниже:

 CREATE TABLE `students` (
  `FirstName` varchar(25),
  `MiddleName` varchar(25),
  `Lastname` varchar(25),
 `StudentNumber` int(6)
);
INSERT INTO students (FirstName,MiddleName,Lastname,StudentNumber) VALUES ('Steve', 'Glenn', 'Bronze', 2591);
INSERT INTO students (FirstName,MiddleName,Lastname,StudentNumber) VALUES ('James', 'Paul', 'Smith', 2592);
INSERT INTO students (FirstName,MiddleName,Lastname,StudentNumber) VALUES ('Al', 'Matt', 'Sutter', 2593);


CREATE TABLE `attendance` (
  `Activity_Id` int(8) NOT NULL,
  `StudentNumber` int(6) DEFAULT NULL,
  `Activity_Location` varchar(17) DEFAULT NULL,
  `Entry_Date` datetime DEFAULT NULL,
  `Offline_Total_Hours` varchar(5) DEFAULT NULL,
  `Online_Total_Hours` varchar(6) DEFAULT NULL,
  `Record_Status` varchar(9) DEFAULT NULL,
  `Student_Email` varchar(24) DEFAULT NULL,
  `Attendance_Activity` varchar(100) DEFAULT NULL,
  `Attendance_Type` varchar(19) DEFAULT NULL,
  `Time_End` datetime DEFAULT NULL,
  `Time_End_Online` varchar(19) DEFAULT NULL,
  `Time_Start` datetime DEFAULT NULL,
  `Time_Start_Online` varchar(19) DEFAULT NULL,
  `TotalHoursDay` decimal(3,2) DEFAULT NULL,
  `Staff_id` int(4) DEFAULT NULL,
  `Override_Reason` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `attendance`
--

INSERT INTO `attendance` (`Activity_Id`, `StudentNumber`, `Activity_Location`, `Entry_Date`, `Offline_Total_Hours`, `Online_Total_Hours`, `Record_Status`, `Student_Email`, `Attendance_Activity`, `Attendance_Type`, `Time_End`, `Time_End_Online`, `Time_Start`, `Time_Start_Online`, `TotalHoursDay`, `Staff_id`, `Override_Reason`) VALUES
(110, 2591, 'Lab', '2019-09-09 00:10:38', NULL, NULL, NULL, NULL, 'Online', '1', '2019-09-09 23:57:00', NULL, '2019-09-09 22:27:00', NULL, NULL, 0, ''),
(113, 2591, 'Lab', '2019-09-09 06:34:08', NULL, NULL, NULL, NULL, 'Online', '1', '2019-09-09 06:33:00', NULL, '2019-09-09 00:34:00', NULL, NULL, 0, ''),
(114, 2592, 'Lab', '2019-09-09 07:22:20', NULL, NULL, NULL, NULL, 'Online', '1', '2019-09-09 08:21:00', NULL, '2019-09-09 07:21:00', NULL, NULL, 0, ''),
(116, 2592, 'Lab', '2019-09-09 07:44:06', NULL, NULL, NULL, NULL, 'Online', '1', '2019-09-09 12:30:00', NULL, '2019-09-09 07:00:00', NULL, NULL, 0, '');


  

Я хочу показать запись в запросе, чтобы она показывала идентификатор 2593, в котором нет записей о посещаемости, поэтому я хочу, чтобы он сообщал 0 в столбце totalhours.

выберите 
 студенты.Количество студентов,
 IFNULL(round(сумма(TimestampDiff(минута, Time_Start, Time_End)) / 60, 2), 0) как общее количество часов 
из 
 студенты 
 левое соединение 
 посещаемость 
 о студентах.Номер студента = посещаемость.StudentNumber 
где 
 time_start между '2019-01-01' и '2020-09-12' 
Группировать по 
 студенты.Количество студентов

https://www.db-fiddle.com/f/iZDMnePyCvzoW82eScXoRF/0

Ответ №1:

вы можете поместить предложение time where в подвыборку для посещаемости, и тогда вы получите результат wnted.

Вы должны заменить SELECT * FROM attendance WHERE time_start BETWEEN '2019-01-01' AND '2020-09-12' только те столбцы, которые вам действительно нужны


Запрос # 1

 SELECT 
    students.StudentNumber,
    IFNULL(ROUND(SUM(TIMESTAMPDIFF(MINUTE,
                        Time_Start,
                        Time_End)) / 60,
                    2),
            0) AS TotalHours
FROM
    students
        LEFT JOIN
    attendance ON students.StudentNumber = attendance.StudentNumber
WHERE
    time_start BETWEEN '2019-01-01' AND '2020-09-12' or time_start IS NULL
GROUP BY students.StudentNumber;

| StudentNumber | TotalHours |
| ------------- | ---------- |
| 2591          | 7.48       |
| 2592          | 6.50       |
| 2593          | 0.00       |
  

Запрос # 2

 SELECT 
    s.StudentNumber
    ,
    IFNULL(ROUND(SUM(TIMESTAMPDIFF(MINUTE,
                        Time_Start,
                        Time_End)) / 60,
                    2),
            0) AS TotalHours
    
FROM
    students s
        LEFT JOIN
    ( SELECT * FROM attendance WHERE
    time_start BETWEEN '2019-01-01' AND '2020-09-12') a ON s.StudentNumber = a.StudentNumber
GROUP BY s.StudentNumber;

| StudentNumber | TotalHours |
| ------------- | ---------- |
| 2591          | 7.48       |
| 2592          | 6.50       |
| 2593          | 0.00       |
  

Просмотр в скрипте DB

Комментарии:

1. nbk это было именно то, что мне было нужно!

2. @ruiner но обратите внимание, что в данном случае подзапрос не нужен

3. Да, если a или time_start РАВНО NULL, вы получите тот же результат