如何使用PHP、MySQL和HTML隐藏查询数据中的重复内容
解决查询结果重复字段隐藏的问题
首先得指出你当前代码里的一个小问题:你用了GROUP BY tally_head.head,这会导致每个tally_head.head只返回一条记录,但实际上你应该是想展示每个凭证(entry)对应的所有ledger条目,只是希望隐藏前面重复的凭证信息,对吧?所以第一步要调整SQL,去掉GROUP BY,保留所有关联的数据,确保我们能拿到每个凭证对应的所有ledger记录:
SELECT entry.id as cid, entry.payorder, entry.bank, entry.PFMS_SCHEME, entry.name, entry.vendor, tally_head.head, ledgers.amount, entry.po, entry.Description, bank_details.Name as party_name, -- 重命名避免和entry.name冲突 entry.sum as total_sum FROM entry JOIN bank_details ON entry.name = bank_details.id JOIN ledgers ON ledgers.id = entry.id JOIN tally_head ON ledgers.ledger = tally_head.id ORDER BY entry.id, tally_head.head; -- 按凭证ID排序,确保同凭证的记录排在一起
接下来给你两种实现隐藏重复内容的方案,根据你的需求选择:
方案一:简单隐藏重复内容(留空)
这个方案很直观,我们在PHP里记录上一行的凭证ID(cid),每次循环时对比当前行和上一行的cid,如果相同,就把前面重复的字段内容留空,否则正常显示并更新上一行的cid:
<table class="table"> <thead> <tr> <th>Voucher No </th> <th>Payorder </th> <th>Bank </th> <th>PFMS_SCHEME </th> <th>Party Name </th> <th> For</th> <th> Po/agmt/inv N.o </th> <th>Ledger</th> <th>Ledger Amount</th> <th>Description/ Narration</th> <th>sum</th> </tr> </thead> <tbody> <?php $sql = mysqli_query($con, "SELECT entry.id as cid, entry.payorder, entry.bank, entry.PFMS_SCHEME, entry.name, entry.vendor, tally_head.head, ledgers.amount, entry.po, entry.Description, bank_details.Name as party_name, entry.sum as total_sum FROM entry JOIN bank_details ON entry.name = bank_details.id JOIN ledgers ON ledgers.id = entry.id JOIN tally_head ON ledgers.ledger = tally_head.id ORDER BY entry.id, tally_head.head"); $prev_cid = null; // 记录上一行的凭证ID while($row = mysqli_fetch_array($sql)) { $is_same_entry = ($row['cid'] == $prev_cid); ?> <tr> <td><?php echo $is_same_entry ? '' : htmlentities($row['cid']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['payorder']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['bank']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['PFMS_SCHEME']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['party_name']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['vendor']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['po']);?></td> <td><?php echo htmlentities($row['head']);?></td> <td><?php echo htmlentities($row['amount']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['Description']);?></td> <td><?php echo $is_same_entry ? '' : htmlentities($row['total_sum']);?></td> </tr> <?php $prev_cid = $row['cid']; // 更新上一行的凭证ID } ?> </tbody> </table>
方案二:使用HTML rowspan合并单元格(更美观专业)
如果想要更整洁的表格效果,推荐用rowspan合并相同凭证的单元格,这样重复的字段会跨多行显示,视觉体验更好。实现思路是先把数据按凭证ID分组,统计每个凭证对应的记录行数,然后在循环时给第一行的重复字段设置rowspan属性,后续行不再输出这些单元格:
<table class="table"> <thead> <tr> <th>Voucher No </th> <th>Payorder </th> <th>Bank </th> <th>PFMS_SCHEME </th> <th>Party Name </th> <th> For</th> <th> Po/agmt/inv N.o </th> <th>Ledger</th> <th>Ledger Amount</th> <th>Description/ Narration</th> <th>sum</th> </tr> </thead> <tbody> <?php // 先获取所有数据并按凭证ID分组 $sql = mysqli_query($con, "SELECT entry.id as cid, entry.payorder, entry.bank, entry.PFMS_SCHEME, entry.name, entry.vendor, tally_head.head, ledgers.amount, entry.po, entry.Description, bank_details.Name as party_name, entry.sum as total_sum FROM entry JOIN bank_details ON entry.name = bank_details.id JOIN ledgers ON ledgers.id = entry.id JOIN tally_head ON ledgers.ledger = tally_head.id ORDER BY entry.id, tally_head.head"); $entries = []; while($row = mysqli_fetch_array($sql)) { $cid = $row['cid']; if(!isset($entries[$cid])) { $entries[$cid] = []; } $entries[$cid][] = $row; } // 遍历分组后的凭证数据 foreach($entries as $cid => $rows) { $row_count = count($rows); // 当前凭证对应的记录行数 $first_row = true; foreach($rows as $row) { ?> <tr> <?php if($first_row): ?> <!-- 第一行设置rowspan,跨所有同凭证的行 --> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['cid']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['payorder']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['bank']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['PFMS_SCHEME']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['party_name']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['vendor']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['po']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['Description']);?></td> <td rowspan="<?php echo $row_count;?>"><?php echo htmlentities($row['total_sum']);?></td> <?php endif; ?> <!-- 每次都显示的ledger相关字段 --> <td><?php echo htmlentities($row['head']);?></td> <td><?php echo htmlentities($row['amount']);?></td> </tr> <?php $first_row = false; } } ?> </tbody> </table>
注意事项
- 一定要用
ORDER BY entry.id确保同凭证的记录排在一起,否则分组或对比逻辑会失效; - SQL里把
bank_details.Name重命名为party_name,是为了避免和entry.name变量混淆,防止输出错误; - 方案二更适合正式的业务系统,视觉效果更专业,方案一适合快速实现需求。
内容的提问来源于stack exchange,提问作者chidruppa
相关产品推荐
相关产品推荐

