Суммирование общей суммы сборов по годам и разбивка данных в таблицу с указанием года сверху и итога снизу - PullRequest
0 голосов
/ 22 марта 2020

Вот две структуры таблиц (сокращены для MCVE - здесь больше строк не нужно):

++++++++++++++++++++++++++++++++ FEES ++++++++++++++++++++++++++++++++++

fee_id +++ fee_amount +++ fee_date   +++ fee_student_ID +++ fee_paid +++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1      +++  200       +++ 2019-12-05 +++ 1              +++ N       ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2      +++  200       +++ 2020-01-05 +++ 1              +++ N       ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3      +++  200       +++ 2020-01-05 +++ 1              +++ N       ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4      +++  250       +++ 2020-01-05 +++ 2              +++ N       ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5      +++  250       +++ 2020-02-05 +++ 2              +++ N       ++++

Таблицы связаны -> fee_student_ID = student_ID

++++++++++++++++++++ STUDENTS +++++++++++++++++++++

student_ID +++ student_name   +++ student_phone +++ 

+++++++++++++++++++++++++++++++++++++++++++++++++++
1          +++ John Doe       +++ 123456789     +++
+++++++++++++++++++++++++++++++++++++++++++++++++++
2          +++ Jane Doe       +++ 987654321     +++

С помощью моего запроса SQL я могу получить и упорядочить данные (мне нужны только строки, в которых "paid" опаздывает / скоро будет). Что мне нужно, это:

  1. группировать по годам
  2. сумма сумм по годам

Я достиг # 1, как это (и это работает, как ожидалось):

$pdo = new PDO("mysql:host=localhost;dbname=$dbname", $adminDBuser, $adminDBpwd);

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

$stmt = $pdo->prepare(" SELECT tbl_fees.*, tbl_students.*, YEAR(tbl_fees.fee_date) AS yearfee 
FROM tbl_fees, tbl_students 
WHERE tbl_fees.fee_student_ID=tbl_students.student_ID 
AND tbl_fees.fee_paid='N' 
AND tbl_fees.fee_date <= DATE_ADD(NOW(), INTERVAL 7 DAY) 
ORDER BY tbl_fees.fee_date ");

$stmt->execute();

$results = $stmt->fetchAll();

foreach( $results as $row ) {

if ($row['yearfee'] != $yearfee) {
echo "<tr colspan=\"5\" class=\"table-title-year\"><td class=\"table-title-year\">
". $row['yearfee']."
</td></tr>";
//**-- adds a row on top of the list, with the YEAR, and splits the data => OK
}

echo"<tr><td>$fee_id</td><td>",my_formated_date($fee_date),"</td>
<td><a href=\"/student-data.php?id=$student_ID\">$student_name</a></td>
<td>$fee_amount</td><td>$fee_paid</td></tr>\n\r";

}

Теперь, что я хочу добавить, это еще один, в нижней части каждого "разбивки по годам". В этой строке будет показана общая сумма невыплаченных / скоро подлежащих оплате сборов. Как показано ниже, ожидаемый результат:

-----------------------------------------
YEAR : 2019
-----------------------------------------
1 --- John Doe --- 2019-12-05 --- 200 ---
-----------------------------------------
TOTAL : 200
-----------------------------------------
YEAR : 2020
-----------------------------------------
2 --- John Doe --- 2020-01-05 --- 200 ---
3 --- Jane Doe --- 2020-01-05 --- 250 ---
4 --- John Doe --- 2020-02-05 --- 200 ---
5 --- Jane Doe --- 2020-02-05 --- 250 ---
-----------------------------------------
TOTAL : 900
-----------------------------------------

Как мне получить приведенную выше таблицу, используя запрос SQL или PHP?

I ' мы искали MySQL (и другие связанные темы в do c) и этого урока (среди прочих), но не можем найти способ адаптировать его к моему case.

Я тестировал что-то вроде этого, с одним годом или для каждого известного отдельного года (все равно все ошибки выбрасывания ...):

  • SUM (tbl_fees.fee_amount ) ФИЛЬТР (ГДЕ ВЫПИСАТЬСЯ (ГОД ОТ tbl_fees.fee_date) = 2019) AS yearSumTotal1
  • СУММА (tbl_fees.fee_amount) ГДЕ ВЫДЕРЖАТЬ (ГОД ОТ tbl_fees.fee_date) = 10 * 101 AS1 910

Ответы [ 3 ]

1 голос
/ 22 марта 2020
<code><?php
$results = [
    ['id' => 1, 'name' => 'John Doe', 'date' => '2019-12-05', 'amount' => 200],
    ['id' => 2, 'name' => 'John Doe', 'date' => '2020-01-05', 'amount' => 200],
    ['id' => 3, 'name' => 'John Doe', 'date' => '2020-01-05', 'amount' => 250],
    ['id' => 4, 'name' => 'John Doe', 'date' => '2020-02-05', 'amount' => 200],
    ['id' => 5, 'name' => 'John Doe', 'date' => '2020-02-05', 'amount' => 250],
];

$year = '';
$total = 0;

echo '<pre>';
foreach ($results as $row) {
    $rowyear = substr($row['date'], 0, 4);

    if ($year != $rowyear) {
        // avoid displaying in the begining of the table
        if ($total) {
            display_total_row($total);
        }

        display_year_row($rowyear);

        $year = $rowyear;
        $total = 0;
    }

    echo '-----------------------------------------' . PHP_EOL;
    echo sprintf('%d --- %s --- %s --- %s ---', $row['id'], $row['name'], $row['date'], $row['amount']) . PHP_EOL;
    echo '-----------------------------------------' . PHP_EOL;

    $total += $row['amount'];
}

// display last total
display_total_row($total);

echo '
'; функция display_year_row ($ year) {echo '----------------------------------------- '. PHP_EOL; эхо 'ГОД:'. год PHP_EOL; echo '-----------------------------------------'. PHP_EOL; } функция display_total_row ($ total) {echo '---------------------------------------- - '. PHP_EOL; эхо 'ВСЕГО:'. Всего PHP_EOL; echo '-----------------------------------------'. PHP_EOL; }
1 голос
/ 22 марта 2020

Я думаю, что вам просто нужно агрегирование, если вы хотите итоги.

SELECT YEAR(f.fee_date) AS yearfee, SUM(f.fee_amount)
FROM tbl_fees f JOIN
     tbl_students s
     ON f.fee_student_ID = s.student_ID AND
        f.fee_paid = 'N'  AND
        f.fee_date <= DATE_ADD(NOW(), INTERVAL 7 DAY) 
GROUP BY YEAR(tbl_fees.fee_date);

Если вы хотите и исходные данные, и накопительный пакет:

SELECT YEAR(f.fee_date) AS yearfee, s.student_id, f.fee_date, f.fee_amount
FROM tbl_fees f JOIN
     tbl_students s
     ON f.fee_student_ID = s.student_ID AND
        f.fee_paid = 'N'  AND
        f.fee_date <= DATE_ADD(NOW(), INTERVAL 7 DAY) 
UNION ALL
SELECT YEAR(f.fee_date) AS yearfee, NULL, NULL,
       SUM(f.fee_amount)
FROM tbl_fees f JOIN
     tbl_students s
     ON f.fee_student_ID = s.student_ID AND
        f.fee_paid = 'N'  AND
        f.fee_date <= DATE_ADD(NOW(), INTERVAL 7 DAY) 
GROUP BY YEAR(tbl_fees.fee_date)
ORDER BY yearfree,
         (fee_date is null) desc,
         fee_date;

Это должно чередовать итоги с Исходные данные.

0 голосов
/ 22 марта 2020

Вы можете использовать довольно большой запрос

SELECT
`fee_id`, `student_name`, fee_date , YEAR(fee_date), SUM(fe.sumfee),SUM(fey.sumfeeeyear)
 FROM FEES f INNER JOIN STUDENTS S ON f.fee_student_ID = student_ID 
 INNER JOIN (SELECT  SUM(`fee_amount`) sumfee, `fee_student_ID`, YEAR(fee_date) yearoffee FROM FEES 
            GROUP by  `fee_student_ID`,YEAR(fee_date)) fe
  ON fe.yearoffee = YEAR(fee_date) AND fe.`fee_student_ID` = f.`fee_student_ID`
 INNER JOIN (SELECT  SUM(`fee_amount`) sumfeeeyear, YEAR(fee_date) yearoffee FROM FEES 
            GROUP by  YEAR(fee_date)) fey
  ON fey.yearoffee = YEAR(fee_date)   
GROUP BY `fee_id`,fee_date,`student_ID`, `student_name`, YEAR(fee_date)
CREATE TABLE  FEES (
  `fee_id` INTEGER,
  `fee_amount` INTEGER,
  `fee_date` VARCHAR(10),
  `fee_student_ID` INTEGER,
  `fee_paid` VARCHAR(1)
);

INSERT INTO  FEES
  (`fee_id`, `fee_amount`, `fee_date`, `fee_student_ID`, `fee_paid`)
VALUES
  ('1', '200', '2019-12-05', '1', 'N'),
  ('2', '200', '2020-01-05', '1', 'N'),
  ('3', '200', '2020-01-05', '1', 'N'),
  ('4', '250', '2020-01-05', '2', 'N'),
  ('5', '250', '2020-02-05', '2', 'N');

CREATE TABLE STUDENTS (
  `student_ID` INTEGER,
  `student_name` VARCHAR(10),
  `student_phone` INTEGER
);

INSERT INTO STUDENTS
  (`student_ID`, `student_name`, `student_phone`)
VALUES
  ('1', 'John Doe', '123456789'),
  ('2', 'Jane Doe2', '987654321');
✓

✓

✓

✓
SELECT
`fee_id`, `student_name`, fee_date , YEAR(fee_date), SUM(fe.sumfee),SUM(fey.sumfeeeyear)
 FROM FEES f INNER JOIN STUDENTS S ON f.fee_student_ID = student_ID 
 INNER JOIN (SELECT  SUM(`fee_amount`) sumfee, `fee_student_ID`, YEAR(fee_date) yearoffee FROM FEES 
            GROUP by  `fee_student_ID`,YEAR(fee_date)) fe
  ON fe.yearoffee = YEAR(fee_date) AND fe.`fee_student_ID` = f.`fee_student_ID`
 INNER JOIN (SELECT  SUM(`fee_amount`) sumfeeeyear, YEAR(fee_date) yearoffee FROM FEES 
            GROUP by  YEAR(fee_date)) fey
  ON fey.yearoffee = YEAR(fee_date)   
GROUP BY `fee_id`,fee_date,`student_ID`, `student_name`, YEAR(fee_date)
fee_id | student_name | fee_date   | YEAR(fee_date) | SUM(fe.sumfee) | SUM(fey.sumfeeeyear)
-----: | :----------- | :--------- | -------------: | -------------: | -------------------:
     1 | John Doe     | 2019-12-05 |           2019 |            200 |                  200
     2 | John Doe     | 2020-01-05 |           2020 |            400 |                  900
     3 | John Doe     | 2020-01-05 |           2020 |            400 |                  900
     4 | Jane Doe2    | 2020-01-05 |           2020 |            500 |                  900
     5 | Jane Doe2    | 2020-02-05 |           2020 |            500 |                  900

db <> fiddle здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...