По сути, то, что у меня есть , работает , но не является лучшей практикой.
Вот мой текущий вывод, который я и хочу, но мне интересно, могу ли я запросить этоданные с одним (хотя и сложным) запросом вместо 5-10 отдельных запросов.(3-7 в выражении foreach, которое я хотел бы исключить.)
Если бы я мог получить все данные в одном запросе,поместите его в массив, а затем извлеките его в таблицу соответственно, это будет более эффективно.
Но я не очень разбираюсь в MySQL и не знаю, как запрашивать несколько сумм конкретных данных, для которых требуется конкретный WHERE.критерии ...
Вот пример моих таблиц: (реальные таблицы более сложные, но я думаю, что это упрощено, так что это понятно.)
+-------------------------------------+
| crop_plans |
+-------------------------------------+
| ID | advisor_id | acres | crop_year |
+----+------------+-------+-----------+
| 1 | 3 | 1000 | 2018 |
+----+------------+-------+-----------+
| 2 | 1 | 1500 | 2019 |
+----+------------+-------+-----------+
| 3 | 2 | 300 | 2017 |
+----+------------+-------+-----------+
| 4 | 2 | 600 | 2018 |
+----+------------+-------+-----------+
| 5 | 3 | 800 | 2017 |
+----+------------+-------+-----------+
+---------------------+
| users |
+---------------------+
| user_id | full_name |
+---------+-----------+
| 1 | Dude A |
+---------+-----------+
| 2 | Dude B |
+---------+-----------+
| 3 | Dude C |
+---------+-----------+
+----------------------+
| advisors |
+----------------------+
| advisor_id | user_id |
+------------+---------+
| 1 | 1 |
+------------+---------+
| 2 | 2 |
+------------+---------+
| 3 | 3 |
+------------+---------+
Вот мои запросы иподумав, а затем код:
Сначала я вытащил получить имя советника (и ID):
SELECT ad.advisor_id AS this_advisor_id, ua.full_name AS full_name
FROM advisors AS ad
JOIN users AS ua ON ad.user_id = ua.user_id
WHERE advisor_id > 1;
(да, пропуская первый)
Затем для каждого из этих результатов я запрашиваю СУММУ акров за данный год, где советник является советником в этой «строке»:
SELECT *
FROM
(
SELECT SUM(acres) AS current_year_acres
FROM crop_plans
WHERE crop_year = ? AND advisor_id = ?
) a CROSS JOIN (
SELECT SUM(acres) AS last_year_acres
FROM crop_plans
WHERE crop_year = ? AND advisor_id = ?
) b CROSS JOIN (
SELECT SUM(acres) AS year_before_acres
FROM crop_plans
WHERE crop_year = ? AND advisor_id = ?
) c;
И, наконец, я запрашиваюитоги: (не зависит от советника)
SELECT *
FROM
(
SELECT SUM(acres) AS current_year_acres
FROM crop_plans
WHERE crop_year = ?
) a CROSS JOIN (
SELECT SUM(acres) AS last_year_acres
FROM crop_plans
WHERE crop_year = ?
) b CROSS JOIN (
SELECT SUM(acres) AS year_before_acres
FROM crop_plans
WHERE crop_year = ?
) c
И с этими результатами я отображаюих с PHP и т. д., чтобы это выглядело так, как вы видите на скриншоте выше.
Вот полный (рабочий, но не идеальный) код:
<?php
echo '<table class="table table-striped table-hover dashboard"><thead><tr>';
echo '<th>Advisor</th><th>'.$current_year.'</th><th>'.$last_year.'</th><th>'.$year_before.'</th>'; // Header
echo '</tr></thead><tbody>';
$sql_retreive = $con->prepare("SELECT ad.advisor_id AS this_advisor_id, ua.full_name AS full_name FROM advisors AS ad JOIN users AS ua ON ad.user_id = ua.user_id WHERE advisor_id > 1;");
$sql_retreive->execute();
$result = $sql_retreive->get_result();
if($result->num_rows >0 ){
while($row=$result->fetch_assoc()){
extract($row); // assigns respective values
echo '<tr>'; // start row
echo '<td><!--'.$this_advisor_id.'-->'.$full_name.'</td>'; // First column
// query database for each advisor
$sql_retreive_in = $con->prepare("SELECT * FROM (SELECT SUM(acres) AS current_year_acres FROM crop_plans WHERE crop_year = ? AND advisor_id = ?) a CROSS JOIN (SELECT SUM(acres) AS last_year_acres FROM crop_plans WHERE crop_year = ? AND advisor_id = ?) b CROSS JOIN (SELECT SUM(acres) AS year_before_acres FROM crop_plans WHERE crop_year = ? AND advisor_id = ?) c;");
$bind_process_in = $sql_retreive_in->bind_param('sisisi',$current_year,$this_advisor_id,$last_year,$this_advisor_id,$year_before,$this_advisor_id);
$sql_retreive_in->execute();
$result_in = $sql_retreive_in->get_result();
if($result_in->num_rows >0 ){
while($row_in=$result_in->fetch_assoc()){
extract($row_in); // assigns respective values
echo '<td>'.format($current_year_acres,'lunit').'</td><td>'.format($last_year_acres,'lunit').'</td><td>'.format($year_before_acres,'lunit').'</td>'; // Remaining columns
} // end of inside while
} // end of inside num_rows >0
echo '</tr>'; // end row
} // end of while
} // end of num_rows >0
// Final totals line
echo '<tr>'; // start row
echo '<td> Total</td>'; // First column
$sql_retreive = $con->prepare("SELECT * FROM (SELECT SUM(acres) AS current_year_acres FROM crop_plans WHERE crop_year = ?) a CROSS JOIN (SELECT SUM(acres) AS last_year_acres FROM crop_plans WHERE crop_year = ?) b CROSS JOIN (SELECT SUM(acres) AS year_before_acres FROM crop_plans WHERE crop_year = ?) c");
$bind_process = $sql_retreive->bind_param('sss',$current_year,$last_year,$year_before);
$sql_retreive->execute();
$result = $sql_retreive->get_result();
if($result->num_rows >0 ){
while($row=$result->fetch_assoc()){
extract($row); // assigns respective values
echo '<td>'.format($current_year_acres,'lunit').'</td><td>'.format($last_year_acres,'lunit').'</td><td>'.format($year_before_acres,'lunit').'</td>'; // Remaining columns
} // end of while
} // end of num_rows >0
echo '</tr>'; // end row
// echo "<tr><td colspan='100%'></td></tr>";
echo "</tbody></table>";
?>
Я быочень благодарен за любые хорошие предложения о том, как я могу исключить запрос в операторе foreach (предварительно собрав все эти значения с помощью запроса и поместив их в массив.)