Как запустить цикл с php MySQL отображать результаты по месяцам с общим значением столбцов - PullRequest
0 голосов
/ 23 октября 2018

Я пытаюсь получить вывод, как показано ниже:

enter image description here

Ниже приведена структура и записи моей таблицы:

enter image description here

Я пробовал с приведенным ниже запросом:

$from_date = '2018-04-01';  
$to_date = '2018-09-01';  

$cid = mysqli_query($con_db,"SELECT * FROM tbl_silver_stock WHERE stockdate between '$from_date' and '$to_date'");

У меня возникла проблема с тем, как проверить, завершен ли месяц и получены ли общие значения столбцов.

Пожалуйста, помогите мне.

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Я оставлю вам стилизацию и оптимизации для вас.Обычно я хотел бы идентифицировать «группы» или «партии» с временным значением и вести подсчет сумм столбцов, пока я зацикливаю данные.Однако из-за того, что столбцов было так много, я передумал на полпути к разработке и решил использовать array_column() и array_sum().Любой метод будет просто найти, IMO.

Что касается стабильности / безопасности:

  1. Хорошая идея проверить, что ожидаемые данные отправки существуют, прежде чем пытаться получить доступ к значениям.
  2. Рекомендуется также выполнить некоторый уровень проверки представленных данных.Как далеко вы продвинетесь в этом, зависит от вас.
  3. Вам нужно использовать подготовленное утверждение, потому что плохая идея разрешать предоставленным пользователем данным беспрепятственно переходить в ваш запрос.
  4. КогдаВы закончили разработку / тестирование своего кода, обязательно удалите сообщения об ошибках.Вы не должны позволять общественности видеть сообщения об ошибках, поскольку они содержат ценные сведения, которые могут использовать злоумышленники.

Протестированный код:

$_GET['from'] = '2018-04-01';
$_GET['to'] = '2018-09-18';

$config = ['localhost', 'root', '', 'dbname'];
$sql = "SELECT DATE_FORMAT(stockdate, '%Y-%m') AS batch,
               DATE_FORMAT(stockdate, '%e-%c-%Y') AS formatteddate,
               particulars,
               vch_type,
               vch_number,
               in_quantity,
               in_price_value,
               out_quantity,
               out_price_value,
               cls_quantity,
               cls_price_value
        FROM tbl_silver_stock
        WHERE stockdate BETWEEN ? AND ?
        ORDER BY stockdate, particulars";
if (!$conn = new mysqli(...$config)) {
    echo "Database Connection Error: $conn->connect_error";
} elseif (!$stmt = $conn->prepare($sql)) {
    echo "Prepare Syntax Error: $conn->error";
} elseif (!$stmt->bind_param("ss", $_GET['from'], $_GET['to']) || !$stmt->execute() || !$result = $stmt->get_result()) {
    echo "Statement Error: $stmt->error";
} elseif (!$result->num_rows) {
    echo "No Rows between {$_GET['from']} and {$_GET['to']}";
} else {
    while ($row = $result->fetch_assoc()) {
        $results[] = $row;                   // for grand total
        $batch[array_shift($row)][] = $row;  // group by year-month value
    }

    ?>
    <table border=1>
        <tr>
            <td rowspan=2>Date</td>
            <td rowspan=2>Particulars</td>
            <td rowspan=2>Vch Type</td>
            <td rowspan=2>Vch No</td>
            <td colspan=2>Inwards</td>
            <td colspan=2>Outwards</td>
            <td colspan=2>Closing</td>
        </tr>
        <tr>
            <td>Quantity</td>
            <td>Value</td>
            <td>Quantity</td>
            <td>Value</td>
            <td>Quantity</td>
            <td>Value</td>
        </tr>
        <?php
        foreach ($batch as $ym => $rows) {
            foreach ($rows as $row) {
                echo "<tr>";
                    echo "<td>{$row['formatteddate']}</td>";
                    echo "<td>{$row['particulars']}</td>";
                    echo "<td>{$row['vch_type']}</td>";  // a lookup array or table join is required for these values
                    echo "<td>" , ($row['vch_number'] == 0 ? '' : $row['vch_number']) , "</td>";
                    echo "<td>" , ($row['in_quantity'] == 0 ? '' : "{$row['in_quantity']}KG") , "</td>";
                    echo "<td>" , ($row['in_price_value'] == 0 ? '' : number_format($row['in_price_value'], 2)) , "</td>";
                    echo "<td>" , ($row['out_quantity'] == 0 ? '' : "{$row['out_quantity']}KG") , "</td>";
                    echo "<td>" , ($row['out_price_value'] == 0 ? '' : number_format($row['out_price_value'], 2)) , "</td>";
                    echo "<td>" , ($row['cls_quantity'] == 0 ? '' : "{$row['cls_quantity']}KG") , "</td>";
                    echo "<td>" , ($row['cls_price_value'] == 0 ? '' : number_format($row['cls_price_value'], 2)) , "</td>";
                echo "</tr>";
            }
            $sum['in_quantity'] = array_sum(array_column($rows, 'in_quantity'));
            $sum['in_price_value'] = array_sum(array_column($rows, 'in_quantity'));
            $sum['out_quantity'] = array_sum(array_column($rows, 'out_quantity'));
            $sum['out_price_value'] = array_sum(array_column($rows, 'out_price_value'));
            $sum['cls_quantity'] = array_sum(array_column($rows, 'cls_quantity'));
            $sum['cls_price_value'] = array_sum(array_column($rows, 'cls_price_value'));                    
            echo "<tr>";
                echo "<td colspan=4>Totals as per \"Default\" valuation:</td>";
                echo "<td>" , ($sum['in_quantity'] == 0 ? '' : "{$sum['in_quantity']}KG") , "</td>";
                echo "<td>" , ($sum['in_price_value'] == 0 ? '' : number_format($sum['in_price_value'], 2)) , "</td>";
                echo "<td>" , ($sum['out_quantity'] == 0 ? '' : "{$sum['out_quantity']}KG") , "</td>";
                echo "<td>" , ($sum['out_price_value'] == 0 ? '' : number_format($sum['out_price_value'], 2)) , "</td>";
                echo "<td>" , ($sum['cls_quantity'] == 0 ? '' : "{$sum['cls_quantity']}KG") , "</td>";
                echo "<td>" , ($sum['cls_price_value'] == 0 ? '' : number_format($sum['cls_price_value'], 2)) , "</td>";
            echo "</tr>";
        }
        $grand['in_quantity'] = array_sum(array_column($results, 'in_quantity'));
        $grand['in_price_value'] = array_sum(array_column($results, 'in_price_value'));
        $grand['out_quantity'] = array_sum(array_column($results, 'out_quantity'));
        $grand['out_price_value'] = array_sum(array_column($results, 'out_price_value'));
        $grand['cls_quantity'] = array_sum(array_column($results, 'cls_quantity'));
        $grand['cls_price_value'] = array_sum(array_column($results, 'cls_price_value'));
        echo "<tr>";
            echo "<td colspan=4>Grand Totals as per \"Default\" valuation:</td>";
            echo "<td>" , ($grand['in_quantity'] == 0 ? '' : "{$grand['in_quantity']}KG") , "</td>";
            echo "<td>" , ($grand['in_price_value'] == 0 ? '' : number_format($grand['in_price_value'], 2)) , "</td>";
            echo "<td>" , ($grand['out_quantity'] == 0 ? '' : "{$grand['out_quantity']}KG") , "</td>";
            echo "<td>" , ($grand['out_price_value'] == 0 ? '' : number_format($grand['out_price_value'], 2)) , "</td>";
            echo "<td>" , ($grand['cls_quantity'] == 0 ? '' : "{$grand['cls_quantity']}KG") , "</td>";
            echo "<td>" , ($grand['cls_price_value'] == 0 ? '' : number_format($grand['cls_price_value'], 2)) , "</td>";
        echo "</tr>";
    echo "</table>";
}

Вывод:

enter image description here

0 голосов
/ 05 ноября 2018

Я подошел к этому как к стандартной проблеме с отчетностью.Идея состоит в том, чтобы

  • прочитать в каждой строке базы данных,
  • проверить, изменился ли месяц, вывести итоги за месяц и накопить общие итоги,
  • выходные строки данных,
  • суммарные месячные суммы

в конце данных

  • выходные итоги последних месяцев,
  • выходные данные в целомитоги.

Другие вещи, которые я включил:

  • с использованием подготовленных операторов, всегда хорошая идея
  • извлечение общего кода для функций (форматирование иотображение значений, добавление итогов)

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

Код -

$from_date = '2018-04-01';
$to_date = '2018-09-01';

if ( !$cid = $conn->prepare("SELECT * 
                FROM tbl_silver_stock 
                WHERE stockdate between ? and ?"))   {
    die( "Error:".$conn->error );
}
$cid->bind_param("ss", $from_date, $to_date);
if ( !$cid->execute())  {
    die( "Error:".$cid->error );
}
if ( !$result = $cid->get_result())  {
    die( "Error:".$cid->error );
}

echo '<table><tr><td>Date</td><td>Particulars</td><td>Vch Type</td>
            <td>Vch No</td><td colspan="2">Inwards</td>
            <td colspan="2">Outwards</td><td colspan="2">Closing</td>
        </tr><tr><td colspan="4">&nbsp;</td><td>Quantity</td>
            <td>Value</td><td>Quantity</td><td>Value</td>
            <td>Quantity</td><td>Value</td>
        </tr>';

$sumKeys = ['in_quantity', 'in_price_value', 'out_quantity', 'out_price_value', 'cls_quantity', 'cls_price_value'];
// Create blank totals arrays
$totals = array_fill_keys($sumKeys, 0);
$totalsMonth = array_fill_keys($sumKeys, 0);
$lastMonth = null;
// Set to allow correct formatting
setlocale(LC_MONETARY, 'en_IN');
while ( $entry = $result->fetch_assoc()) {
    $month = date("m-Y", strtotime($entry['stockdate']));
    // If month has changed (but not for first loop)
    if ( ($lastMonth??$month) != $month ) {
        echo '<tr><td colspan="4">Totals as per "Default" valuation:</td>'
            .outputValues($totalsMonth).'</tr>';
        // Add month totals to overall total
        addTotals($totals, $totalsMonth);
        // Reset totals for month
        $totalsMonth = array_fill_keys($sumKeys, 0);
    }
    $lastMonth = $month;
    echo "<tr>
            <td>".date("d-m-Y", strtotime($entry['stockdate']))."</td>
            <td>$entry[particulars]</td>
            <td>$entry[vch_type]</td>
            <td>".(!empty($entry['vch_number'])?$entry['vch_number']:'')."</td>"
            .outputValues($entry)."</tr>";
    // Add current entry to monthly totals
    addTotals($totalsMonth, $entry);
}
// Output last monthly totals
echo '<tr><td colspan="4">Totals as per "Default" valuation:</td>'
    .outputValues($totalsMonth).'</tr>';
addTotals($totals, $totalsMonth);
// Output grand totals
echo '<tr><td colspan="4">Grand Totals as per "Default" valuation:</td>'
        .outputValues($totals).'</tr></table>';

// Output common values with appropriate formatting
function outputValues ( $entry ){
    return "<td>".(!empty($entry['in_quantity'])?$entry['in_quantity']."KG":'&nbsp;')."</td>
        <td>".(!empty($entry['in_price_value'])?money_format('%!i', $entry['in_price_value']):'&nbsp;')."</td>
        <td>".(!empty($entry['out_quantity'])?$entry['out_quantity']."KG":'&nbsp;')."</td>
        <td>".(!empty($entry['out_price_value'])?money_format('%!i', $entry['out_price_value']):'&nbsp;')."</td>
        <td>".(!empty($entry['cls_quantity'])?$entry['cls_quantity']."KG":'&nbsp;')."</td>
        <td>".(!empty($entry['cls_price_value'])?money_format('%!i', $entry['cls_price_value']):'&nbsp;')."</td>";
}
// Add on new values
function addTotals ( &$to, $add )   {
    $to['in_quantity'] += $add['in_quantity'];
    $to['in_price_value'] += $add['in_price_value'];
    $to['out_quantity'] += $add['out_quantity'];
    $to['out_price_value'] += $add['out_price_value'];
    $to['cls_quantity'] += $add['cls_quantity'];
    $to['cls_price_value'] += $add['cls_price_value'];
}
0 голосов
/ 01 ноября 2018

Давайте посмотрим:

$from_date = '2018-04-01';  
$to_date = '2018-09-30';
$is_complete=true; //boolean to check if month is complete
$month_marker=0; //to keep track of month's changes
echo '<table><tr><th>Date</th><th>In price value</th></tr>';
//we add a ORDER BY to make sure we get the lines as needed
$cid = mysqli_query($con_db,"SELECT *,YEAR(stockdate) as year,MONTH(stockdate) as month FROM tbl_silver_stock WHERE stockdate between '$from_date' and '$to_date' ORDER BY stockdate");
while($line=mysqli_fetch_assoc($cid)){
  if($month_marker!=$line['month']){//change of month
    if($month_marker>0)echo '<tr><td>Total for month '.$month_marker.' : </td><td>'.$total_in_price.'</td></tr>';
    $month_marker=$line['month'];
    $total_in_price=0; //the monthly total price of your lines
  }
  if($line['year']>=date('Y') AND $line['month']>=date('m'))$is_complete=false;//here you could use "=" instead of ">=" but it's more robust that way
  echo '<tr><td>'.$line['stockdate'].'</td><td>'.$line['in_price_value'].'</td></tr>';
  $total_in_price+=$line['in_price_value'];
}
if(!$is_complete)$incomplete=' - Incomplete month !';
else $incomplete='';
echo '<tr><td>Total for month '.$month_marker.$incomplete.' : </td><td>'.$total_in_price.'</td></tr>'; //we add this outside the while loop because else we'll miss the last month

echo '</table>';

Он не оптимизирован (вам, вероятно, следует использовать функции для перегруппировки эха вместе, возможно, использовать несколько массивов вместо одноразовых переменных типа $total_in_price и т. Д.) И не тестировать, но вы должны понять суть.

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