Как объединить и суммировать столбец в двух таблицах на основе другого столбца, используя mysqli и php (просто используя запрос) - PullRequest
2 голосов
/ 04 мая 2019

У меня есть 2 таблицы о банке крови:

  1. пожертвования
  2. заказов

в таблице пожертвований У меня есть 2 поля, показывающие, сколько пожертвований у нас есть:

------------------------
| blood_group | amount |
------------------------
|    A+       |   2    |
|    B-       |   3    |
|    O+       |   4    |
|    A+       |   3    |
|    O+       |   1    |

в таблице заказов У меня есть 2 столбца, в которых указано, сколько запросов мы отправляем на основе группы крови:

------------------------
| blood_group | amount |
------------------------
|    A+       |   4    |
|    B-       |   3    |
|    O+       |   4    |
|    AB-      |   6    |

Моя проблема в том, что я хочу использовать запрос mysqli для получения массивакоторые показывают мне этот результат, основываясь на следующих условиях:

  1. показывает, сколько нам нужно группировать по blood_group
  2. , если нам не нужна группа blood_group или у нас нет запроса наэта группа крови показывает ноль (не показывает ноль)
  3. не показывает отрицательное число для нашей нехватки крови

Мне удается сделать это до сих пор:

<?php
$con = mysqli_connect("localhost", "root", "", "test");
// Check connection
if (mysqli_connect_errno()) {
    echo "Failed to connect to MySQL: " . mysqli_connect_error();
}

$sql ="SELECT donates.blood_group as blood_group,
                donates.amount as donates_amount,
                orders.amount as orders_amount,
                                    FROM `donates`
                                    LEFT JOIN `orders` 
                                    ON donates.blood_group = orders.blood_group
                                    GROUP BY donates.blood_group";
// Perform queries
$result = mysqli_query($con, $sql);

if (!$result = mysqli_query($con, $sql)) {
    echo "SQLSTATE error: " . mysqli_sqlstate($con);
    echo "<br>";
    echo "SQLSTATE error: " . mysqli_error($con);
    exit;
}

$result = mysqli_fetch_all($result, MYSQLI_ASSOC);

var_dump($result);

mysqli_close($con);

Этот запрос показывает мне сумму blood_groups, но вот главный вопрос:

Итак, вот основные вопросы:

  1. как вычесть (donates_amount и orders_amount)
  2. как сделать их положительными (сначала вычтите, какой из них)
  3. как показатьрезультат, даже если одна группа крови не представлена ​​в другой (полное объединение)

Ответы [ 2 ]

2 голосов
/ 04 мая 2019

Чтобы ответить на ваш первый вопрос:

как вычесть (donates_amount и orders_amount)

Вы должны использовать функцию SUM () со знаком минус:

SUM(donates.amount - orders.amount);

это вычитает общую сумму из двух таблиц

Но у нас есть некоторая проблема: у вас могут быть нулевые значения (потому что у вас может не быть некоторых групп крови, присутствующих в одной из таблиц)которые дают неправильный результат.Вы должны изменить нулевые значения на ноль с помощью функции COALESCE ():

SUM(COALESCE(donates.amount,0) - COALESCE(orders.amount,0))

Мы должны дополнительно проверить, если результат не равен нулю:

COALESCE(SUM(COALESCE(donates.amount,0) - COALESCE(orders.amount,0)),0)

каксделайте их положительными (сначала вычтите, какое из них)

И наконец, если вы хотите избежать отрицательных чисел, вы должны использовать математические функции mysqli с именем ABS (), которые дают вам абсолютное значение:

ABS(COALESCE(SUM(COALESCE(donates.amount,0) - COALESCE(orders.amount,0)),0))

, поэтому ваш запрос будет выглядеть следующим образом:

$sql = "SELECT donates.blood_group as blood_group,
          COALESCE(donates.amount,0) as donates_amount,
          COALESCE(orders.amount,0) as orders_amount,
          ABS(COALESCE(SUM(COALESCE(donates.amount,0) - COALESCE(orders.amount,0)),0)) as needed_amount
                                    FROM `donates`
                                    LEFT JOIN `orders` 
                                    ON donates.blood_group = orders.blood_group
                                    GROUP BY donates.blood_group";

как показать результат, даже если одна группа крови не представлена ​​в другой (полное объединение)

Чтобы выполнить полное объединение, вы должны использовать объединение с формой invers вашего запроса.так что вы найдете другие записи в таблице заказов и объедините результаты в один результат:

$sql = "SELECT donates.blood_group as blood_group,
          COALESCE(donates.amount,0) as donates_amount,
          COALESCE(orders.amount,0) as orders_amount,
          ABS(COALESCE(SUM(COALESCE(donates.amount,0) - COALESCE(orders.amount,0)),0)) as needed_amount
              FROM `donates`
              LEFT JOIN `orders` 
              ON donates.blood_group = orders.blood_group
              GROUP BY donates.blood_group 
              UNION
         SELECT orders.blood_group as blood_group,
            COALESCE(donates.amount,0) as donates_amount,
            COALESCE(orders.amount,0) as orders_amount,
            ABS(COALESCE(SUM(COALESCE(orders.amount,0) - COALESCE(donates.amount,0)),0)) as needed_amount
               FROM `orders`
               LEFT JOIN `donates`
               ON orders.blood_group = donates.blood_group
               GROUP BY orders.blood_group";
0 голосов
/ 04 мая 2019

Используйте union all и group by:

select blood_group, sum(donate_amount) as donate_amount,
       sum(order_amount) as order_amount
from ((select blood_group, amount as donate_amount, 0 as order_amount
       from donates
      ) union all
      (select blood_group, 0 as donate_amount, amount as order_amount
       from orders
      )
     ) od
group by blood_group;

Единственное предостережение в том, что группа крови должна находиться в одной из таблиц.Если у вас есть отдельная таблица всех из них, вы должны использовать это.Например:

select bg.*,
       coalesce(donate_amount, 0) as donate_amount,
       coalesce(order_amount, 0) as order_amount
from blood_groups bg left join
     (select blood_group, sum(amount) as donate_amount
      from donates
      group by blood_group
     ) d
     on d.blood_group = bg.blood_group left join
     (select blood_group, sum(amount) as order_amount
      from donates
      group by blood_group
     ) o
     on o.blood_group = bg.blood_group ;

В любом из этих запросов вы можете получить разницу, используя -, и показать отрицательные числа как 0, используя greatest().Например:

greatest(sum(donate_amount) - sum(order_amount), 0)
...