У меня есть таблица, в которой хранятся данные о труде. Один из столбцов — это количество отработанных часов (rthours) для конкретного проекта, другой столбец — это дата (labour_date).
Мне нужно собрать сумму всех часов, отработанных для каждого дня текущей недели, и поместить их в массив для использования со сценарием построения диаграмм, который генерирует гистограмму.
График начинается в понедельник и заканчивается в воскресенье.
У меня написано следующее предложение выбора, но оно возвращает неправильные значения, оно также не учитывает, если в течение одного дня не было записано ни одного часа.
Какие-либо предложения?
Вот код:
$sql = "SELECT SUM(rthours) as total FROM data WHERE (WEEK(labor_date) = WEEK(NOW())) AND (user_name = '$user') GROUP BY DAY(labor_date) ORDER BY DAY(labor_date)";
$result = mysqli_query($conn, $sql);
$thours = array();
while ($row = mysqli_fetch_assoc($result)) {
$thours[] = $row["total"];
}
mysqli_close($conn);
?>
Прежде всего, ваш код открыт для SQL-инъекция. Я не буду обсуждать это здесь, но, пожалуйста, исправьте это.
Вам нужно использовать функцию weekday
(1 — 7), не day
(1 — 31), так как последний может пересечь границу месяца и затем произвести неправильный порядок.
Чтобы заполнить пробелы, вы можете добавить виртуальную таблицу к вашему запросу, которая будет производить числа от 1 до 7, а затем внешне объединить ваши данные с этим. За пропущенные дни ваша сумма все равно будет включена, но null
, С coalesce
Вы можете превратить это в значение 0:
SELECT COALESCE(SUM(rthours), 0) as total
FROM (SELECT 1 as weekday
UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5
UNION ALL SELECT 6 UNION ALL SELECT 7) as ref
LEFT JOIN data
ON DAYOFWEEK(labor_date) = ref.weekday
WHERE WEEK(labor_date) = WEEK(NOW())
AND user_name = ?
GROUP BY ref.weekday
ORDER BY ref.weekday
Догадаться. Использование этого оператора select работает:
SELECT SUM(rthours) total
FROM data
WHERE (WEEK(labor_date) = WEEK(NOW()))
AND (YEAR(labor_date) = YEAR(NOW()))
AND (user_name = '$user')
GROUP
BY WEEKDAY(labor_date)
ORDER
BY WEEKDAY(labor_date);
Отредактированный код для этого:
"SELECT COALESCE(SUM(rthours) + SUM(othours) + SUM(trthours) + SUM(tothours), 0) as total
FROM (SELECT 1 as weekday
UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5
UNION ALL SELECT 6 UNION ALL SELECT 7) as ref
LEFT JOIN data
ON DAYOFWEEK(labor_date) = ref.weekday
WHERE WEEK(labor_date) = WEEK(NOW()) AND Year(labor_date) = Year(NOW())
AND user_name = '$user'
GROUP BY ref.weekday
ORDER BY ref.weekday";
Код захватывает данные, но все еще не помещает нули, когда данные не существуют в течение определенного дня.