基于MySQL分组设置表格单元格样式及酒店预订日期屏蔽技术问询
基于MySQL分组实现酒店预订表格单元格样式方案
针对你的酒店预订表场景,核心思路是先通过MySQL获取分组关联信息,再结合PHP和前端实现同预订组(bookingid相同)的单元格统一样式。下面分步骤给出具体可落地的方案:
1. 优化SQL查询,拿到分组关联数据
我们需要同时获取每条夜间记录,以及对应预订组的整体统计信息(比如同预订的日期范围、总天数),这样每条记录都能知道自己所属的分组情况。这里分两种MySQL版本的实现:
方案A(MySQL 8.0+,推荐用窗口函数)
窗口函数可以在不聚合行的前提下,直接给每条记录打上分组标记:
SELECT b.id, b.room, b.night, b.bookingid, b.timestamp, -- 同预订的最早/最晚日期 MIN(b.night) OVER (PARTITION BY b.bookingid) AS booking_start, MAX(b.night) OVER (PARTITION BY b.bookingid) AS booking_end, -- 同预订的总夜间数,用于合并单元格计算 COUNT(b.id) OVER (PARTITION BY b.bookingid) AS booking_total_nights FROM bookings b -- 保留你原有的年月筛选逻辑 WHERE b.night BETWEEN '$year-$month-01' AND LAST_DAY('$year-$month-01') ORDER BY b.bookingid, b.night;
方案B(MySQL 5.x兼容,用子查询关联)
如果你的MySQL版本较低,用子查询先统计分组信息再关联原表:
SELECT b.id, b.room, b.night, b.bookingid, b.timestamp, bg.booking_start, bg.booking_end, bg.booking_total_nights FROM bookings b JOIN ( SELECT bookingid, MIN(night) AS booking_start, MAX(night) AS booking_end, COUNT(id) AS booking_total_nights FROM bookings WHERE night BETWEEN '$year-$month-01' AND LAST_DAY('$year-$month-01') GROUP BY bookingid ) bg ON b.bookingid = bg.bookingid WHERE b.night BETWEEN '$year-$month-01' AND LAST_DAY('$year-$month-01') ORDER BY b.bookingid, b.night;
⚠️ 重要提醒:一定要用参数绑定(比如PDO的prepare+execute)替代直接拼接变量到SQL里,避免SQL注入风险。
2. PHP端预处理分组数据
拿到查询结果后,把数据按bookingid分组,方便前端渲染时快速识别同组记录:
// 假设$pdo是你的数据库连接实例 $sql = "上面的SQL语句"; $stmt = $pdo->prepare($sql); // 用参数绑定传递年月,避免注入 $stmt->execute([$year, $month]); $bookings = $stmt->fetchAll(PDO::FETCH_ASSOC); // 按bookingid分组 $groupedBookings = []; foreach ($bookings as $booking) { $groupedBookings[$booking['bookingid']][] = $booking; }
3. 前端表格样式实现(两种常见效果)
效果1:同组行统一背景色
给每个预订组设置交替的背景色,视觉上快速区分不同预订:
<table border="1" cellpadding="8"> <thead> <tr> <th>ID</th> <th>Room</th> <th>Night</th> <th>Booking ID</th> <th>Timestamp</th> </tr> </thead> <tbody> <?php $colorIndex = 0; $groupColors = ['#f8f9fa', '#e9ecef']; // 定义两组浅色系背景 foreach ($groupedBookings as $bookingGroup) { $currentColor = $groupColors[$colorIndex % count($groupColors)]; foreach ($bookingGroup as $row) { ?> <tr style="background-color: <?php echo $currentColor; ?>"> <td><?php echo $row['id']; ?></td> <td><?php echo $row['room']; ?></td> <td><?php echo $row['night']; ?></td> <td><?php echo $row['bookingid']; ?></td> <td><?php echo $row['timestamp']; ?></td> </tr> <?php } $colorIndex++; } ?> </tbody> </table>
效果2:合并同组重复列(比如Room、Booking ID)
利用SQL里拿到的booking_total_nights,实现同预订组的Room和Booking ID单元格合并,让表格更简洁:
<table border="1" cellpadding="8"> <thead> <tr> <th>ID</th> <th>Room</th> <th>Night</th> <th>Booking ID</th> <th>Timestamp</th> </tr> </thead> <tbody> <?php foreach ($groupedBookings as $bookingGroup) { $isFirstRow = true; foreach ($bookingGroup as $row) { $rowspan = $isFirstRow ? $row['booking_total_nights'] : 0; ?> <tr> <td><?php echo $row['id']; ?></td> <?php if ($isFirstRow): ?> <td rowspan="<?php echo $rowspan; ?>"><?php echo $row['room']; ?></td> <?php endif; ?> <td><?php echo $row['night']; ?></td> <?php if ($isFirstRow): ?> <td rowspan="<?php echo $rowspan; ?>"><?php echo $row['bookingid']; ?></td> <?php endif; ?> <td><?php echo $row['timestamp']; ?></td> </tr> <?php $isFirstRow = false; } } ?> </tbody> </table>
内容的提问来源于stack exchange,提问作者Salwa El Bannan




