1

I'm fetching data from two table Tenders and payments I want to display monthly payments with monthly tenders in on array. But I need to compare if the month and year from the first loop is the same as the month and year from the nested loop

$first_sql = "SELECT YEAR(toll.transaction_date) 'year', MONTHNAME(toll.transaction_date) 'month', COUNT(toll.toll_id) 'count', SUM(toll.tender) 'tender' 
                  FROM toll WHERE company_id = '$COMPANY_ID' 
                  GROUP BY YEAR(toll.transaction_date), MONTHNAME(toll.transaction_date), MONTH(toll.transaction_date) 
                  ORDER BY YEAR(toll.transaction_date) DESC, MONTH(toll.transaction_date) DESC limit 5;";
$scnd_sql = "SELECT YEAR(company_payment_detail.payment_date) 'year', MONTHNAME(company_payment_detail.payment_date) 'month', SUM(company_payment_detail.payment_amount) 'payment' 
                    FROM company_payment_detail
                    JOIN company_account ON company_payment_detail.company_account_id = company_account.company_account_id 
                    JOIN company ON company.company_id = company_account.company_id 
                    WHERE company_account.company_id = '$COMPANY_ID' 
                    GROUP BY YEAR(company_payment_detail.payment_date), MONTHNAME(company_payment_detail.payment_date),MONTH(company_payment_detail.payment_date)
                    ORDER BY YEAR(company_payment_detail.payment_date) DESC, MONTH(company_payment_detail.payment_date) DESC limit 5";

The Results

enter image description here

enter image description here

The Loops

$run_first_sql= $conn->query($first_sql);
$run_scnd_sql = $conn->query($scnd_sql);

$chart_data = [];

//first loop

while($row= $run_first_sql->fetch_assoc()){

 $arr1 = array(
      'y' => $row['year'],
      'm' => $row['month'],
      'c' => (int)$row['count'],
      't' => (float)$row['tender']
  ); 
  while($row2= $run_scnd_sql->fetch_assoc()){
    if($row['year'] == $row2['year'] && $row['month'] == $row2['month']){
      $arr2 = array(
        'p' =>(float)$row2['payment'],
      );
   }else{
       $arr2 = array(
        'p' =>(float)0,
      );  
   }
 }
    $arr1 = array_merge($arr1, $arr2);  
  array_push($chart_data1, $arr1);
}

print_r($chart_data1);
Wells
  • 142
  • 1
  • 13

2 Answers2

1

Do a LEFT JOIN of the two queries. If there's no row in the second query for the same month, you'll get NULL in those columns.

SELECT t1.year, t1.month, t1.count, t1.tender, IFNULL(t2.payment, 0) AS payment
FROM (
    SELECT YEAR(toll.transaction_date) 'year', MONTHNAME(toll.transaction_date) 'month', COUNT(toll.toll_id) 'count', SUM(toll.tender) 'tender' 
    FROM toll WHERE company_id = '$COMPANY_ID' 
    GROUP BY year, month 
    ORDER BY year DESC, month DESC 
    limit 5) AS t1
LEFT JOIN (
        SELECT YEAR(company_payment_detail.payment_date) 'year', MONTHNAME(company_payment_detail.payment_date) 'month', SUM(company_payment_detail.payment_amount) 'payment' 
    FROM company_payment_detail
    JOIN company_account ON company_payment_detail.company_account_id = company_account.company_account_id 
    JOIN company ON company.company_id = company_account.company_id 
    WHERE company_account.company_id = '$COMPANY_ID' 
    GROUP BY year, month 
    ORDER BY year DESC, month DESC 
    limit 5) AS t2
ON t1.year = t2.year AND t1.month = t2.month
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You can perform that in a single query, the year and month of both table can be used as their relationship. The query will be looked like this:

$sql = 'SELECT * FROM tenders, payments WHERE tenders.year=payments.year AND tenders.month=payments.month';

while($row = $sql ->fetch_assoc()){
     $data = array(
         'month' => $row2['month'],
         'year' => $row2['year'],
         'count' => $row2['count'],
         'tender' => $row2['tender'],
      );
 }

All the tenders year that is equal to payments year AND tenders month that is equal payments month will be fetched.

So if you are going to stick with your way of fetching data, your if condtion code will look like this:

 while($row = $run_first_sql->fetch_assoc()){
    while($row2 = $scnd_sql ->fetch_assoc()){
        if($row['month'] == $row2['month'] && $row['year'] == $row2['year']){
            $data = array(
                'month' => $row['month'],
                'year' => $row['year'],
                'count' => $row['count'],
                'tender' => $row['tender'],
            );
        }
    }
}

The data of the first query as it iterate will be checked in your second query which takes time.

freetzyy
  • 46
  • 6
  • Don't use old-style cross-products when teaching newbies, use ANSI JOIN. – Barmar Feb 06 '20 at 13:29
  • Nested loops won't work with `fetch()`, because the first iteration of the outer loop will read all the rows from the inner loop, and there won't be anything left to process. – Barmar Feb 06 '20 at 13:30
  • Your query doesn't do any of the aggregation in his query. – Barmar Feb 06 '20 at 13:32
  • So you are saying that in my previous coding style which I used his/her way of coding by iterating is not working? So all of my works is a lie? It seems that you are better than me and I am teaching him the way I solve that during my newbie time @Barmar – freetzyy Feb 06 '20 at 13:36