У меня есть таблица table_order, как показано ниже:
orderid | orderdate | price | deptnr
--------+-------------+--------+----------
1 | 2019-07-12 | 50000 | 1
2 | 2019-07-12 | 30000 | 1
3 | 2019-07-13 | 40000 | 1
4 | 2019-07-14 | 50000 | 1
Мне нужно вывести весь столбец в table_order с условием, что если есть одна и та же дата, значение price будет накапливаться в одну запись (записи в столбцах 1 и 2 должны быть объединены с общей ценой 50000+30000). Вот что я сделал:
// $sql = mysqli_query($con, "SELECT * FROM table_order
// WHERE deptnr='$departmetnnr' AND orderstatus='CLOSE'
// AND orderdate BETWEEN '$oneyearbefore' AND '$currentdate' ORDER BY orderdate");
$sql = mysqli_query($con, "
SELECT SUM(price) AS totalprice
FROM table_order
WHERE deptnr = '$departmetnnr'
AND orderstatus='CLOSE'
AND orderdate BETWEEN '$oneyearbefore' AND '$currentdate'
ORDER
BY orderdate
");
$data = array();
while($row=mysqli_fetch_assoc($sql)) {
$data[] = ($row);
}
$json = json_encode($data);
Честно говоря, я новичок в PHP и SQL, я пытаюсь создать простой веб-сервис для мобильных приложений, поэтому я хочу обрабатывать все вычисления на сервере и выводить в виде JSON.
Я прочитал некоторые базовые утверждения о PHP и SQL (в w3school, когда-то в ответе на переполнение стека), проблема, связанная с моей, например это, но я еще не нашел правильный вывод. Я люблю читать любые предложения / справочные ссылки, если таковые имеются. Заранее спасибо.






Вам нужно GROUP BY orderdate, если вы хотите получить сумму за каждую дату. Это создает одну группу для каждого из различных значений orderdate, и затем вы можете использовать агрегатную функцию SUM(), чтобы получить каждую сумму для каждой группы (так что для вас это сумма цен для каждой даты).
Если вы не укажете GROUP BY orderdate, вы просто получите сумму по всем строкам.
SELECT SUM(price) as totalprice, orderdate
FROM table_order
WHERE deptnr='$departmetnnr'
AND orderstatus='CLOSE'
AND orderdate BETWEEN '$oneyearbefore' AND '$currentdate'
GROUP BY orderdate
ORDER BY orderdate
Тем не менее, в настоящее время вы вводите переменные непосредственно в запрос, чего следует избегать, используя подготовленный оператор.
$stmt = $con->prepare("SELECT SUM(price) as totalprice, orderdate
FROM table_order
WHERE deptnr=?
AND orderstatus='CLOSE'
AND orderdate BETWEEN ? AND ?
GROUP BY orderdate
ORDER BY orderdate");
$stmt->bind_param("sss", $departmetnnr, $oneyearbefore, $currentdate);
$stmt->execute();
$stmt->bind_result($totalprice, $orderdate);
while ($stmt->fetch()) {
$data[] = ["totalprice" => $totalprice, "orderdate" => $orderdate];
}
$stmt->close();
$json = json_encode($data);
Вы также можете использовать функции SQL для создания 1 года в прошлом и получения текущей даты вместо использования значений PHP. Используйте CURDATE(), чтобы получить текущую дату, затем определите интервал в 1 год, из которого вы вычтете, они станут диапазонами для вашего BETWEEN.
$stmt = $con->prepare("SELECT SUM(price) as totalprice, orderdate
FROM table_order
WHERE deptnr=?
AND orderstatus='CLOSE'
AND orderdate BETWEEN CURDATE() AND CURDATE() - INTERVAL 1 YEAR
GROUP BY orderdate
ORDER BY orderdate");
$stmt->bind_param("s", $departmetnnr);
$stmt->execute();
$stmt->bind_result($totalprice, $orderdate);
while ($stmt->fetch()) {
$data[] = ["totalprice" => $totalprice, "orderdate" => $orderdate];
}
$stmt->close();
$json = json_encode($data);
И что это за ошибка? И вы должны использовать всегдаprepare(), когда вам нужны переменные PHP в запросе. Всегда! Это сделано для того, чтобы в худшем случае предотвратить SQL-инъекцию, а в лучшем случае – чтобы данные не нарушили ваш запрос.
о, обычно я помещаю переменную непосредственно в оператор sql, потому что переменная имеет значение заголовка HTTP, затем я пытаюсь изменить с помощью подготовки. Ошибка Uncaught Error: Call to a member function bind_param() on bool in
Не используйте переменные в запросе — используйте заполнители и используйте prepare(), особенно те, которые получены из любого пользовательского ввода. -- Я не вижу deptnr в приведенном выше определении таблицы. Это часть таблицы table_order? $stmt будет логическим значением, если запрос завершится ошибкой (что произойдет независимо от того, используете ли вы prepare() или query() — не используйте query() здесь.. ;-)
Вы можете добавить mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); перед созданием соединения new mysqli()/mysqli_connect(), чтобы получить более конкретные ошибки.
ах даа извините, deptnr является частью столбца в table_order, я отредактирую вопрос
Как указано выше, добавьте строку с mysqli_report() перед подключением, и вы получите исключение с Зачем, запрос не выполнен.
Спасибо за все советы, теперь это решается с небольшими изменениями :)
Вам нужно добавить GROUP BY orderdate, и все готово.
Зачем использовать подготовку ?? кстати, ваше объяснение очень-очень ясное, но все же есть ошибка в соответствии с
bind_param