同一医生表双SELECT查询合并与过滤问题求助
问题分析与解决方案
先梳理你代码里的几个核心问题,咱们一步步把它搞定:
1. 星期格式不匹配
你用date('l', strtotime($date))得到的是完整星期名(比如Monday),但你的表中day1-day7存储的是缩写(mon/tue),这俩完全不匹配,自然查不到数据。应该改用strtolower(date('D', strtotime($date)))获取小写的星期缩写(返回mon/tue),和表中的存储格式对齐。
2. SQL逻辑与语法错误
- UNION写法错误:你把
UNION写在了mysqli_query的参数外面,语法完全不对。而且其实你根本不需要UNION——两个查询都是针对同一个表、同一个id,直接合并成一个条件就行。 - 逻辑运算符优先级问题:
AND的优先级比OR高,你原来的DAY1='$day' OR DAY2='$day' AND DAY3='$day'会被解析成DAY1='$day' OR (DAY2='$day' AND DAY3='$day'),这和你想要的「任意一个day字段匹配」完全不符,必须把所有OR条件用括号括起来。
3. 变量名错误
你用$row = mysqli_fetch_array($sql)获取结果,但后面却用$row1来取值,这肯定拿不到数据,变量名要统一。
4. SQL注入风险
直接把$available和$date拼到SQL里,存在严重的注入风险,必须用预处理语句绑定参数来规避。
修正后的完整代码
<?php session_start(); include 'connect.php'; // 先判断日期是否为空,提前拦截 if(empty($_GET['date'])) { echo "ENTER DATE PLEASE"; exit; } if(isset($_GET['submit'])) { $date = $_GET['date']; $available = $_SESSION['available']; // 获取和表中格式匹配的小写星期缩写 $day = strtolower(date('D', strtotime($date))); // 使用预处理语句,彻底避免SQL注入 $sql = "SELECT id, specilization, doctorName, docFees, starttime, endtime, date1 FROM doctors WHERE id = ? AND ( CAST(date1 AS DATE) = ? OR day1 = ? OR day2 = ? OR day3 = ? OR day4 = ? OR day5 = ? OR day6 = ? OR day7 = ? )"; $stmt = mysqli_prepare($mysqli, $sql); // 绑定参数:s表示字符串,若id是整数可改成i mysqli_stmt_bind_param($stmt, "sssssssss", $available, $date, $day, $day, $day, $day, $day, $day, $day); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); // 检查是否有匹配结果 if(mysqli_num_rows($result) > 0) { echo "Day: ". $day . "<br>"; echo "<table>"; // 循环输出所有匹配结果(支持多条数据) while($row = mysqli_fetch_assoc($result)) { ?> <tr> <td><?php echo $row['id'];?></td> <td><?php echo $row['specilization'];?></td> <td><?php echo $row['doctorName'];?></td> <td><?php echo $row['docFees'];?></td> <td><?php echo $row['starttime'];?></td> <td><?php echo $row['endtime'];?></td> <td><?php echo $_SESSION['bdate'];?></td> </tr> <?php } echo "</table>"; } else { echo "No doctor available on this date."; } // 关闭语句和连接,养成好习惯 mysqli_stmt_close($stmt); mysqli_close($mysqli); } ?>
额外优化建议
- 你的表结构有点冗余,
day1-day7这种字段可以改成单独的available_days字段,存储逗号分隔的星期缩写(比如mon,tue,wed),然后用FIND_IN_SET(?, available_days)查询,表结构更简洁,维护也更方便。 - 记得对用户输入做验证,比如检查
$date是否是有效的日期格式,可以用DateTime::createFromFormat来校验:
if(!DateTime::createFromFormat('Y-m-d', $date)) { echo "Please enter a valid date in YYYY-MM-DD format."; exit; }
内容的提问来源于stack exchange,提问作者Nilanjana Maiti
相关产品推荐
相关产品推荐

