PHP MySQL根据列/行值选择多个表
Posted
技术标签:
【中文标题】PHP MySQL根据列/行值选择多个表【英文标题】:PHP MySQL Selecting Multiple Tables Based on Column/Row Value 【发布时间】:2021-12-20 21:44:19 【问题描述】:我只是根据我的“学生”表的值对一些我试图将它们关联在一起的表进行一些测试。
这是我拥有的总表:
学生表
id, name, course_num, msg_num
生物学表
id、详细信息、msg_num
化学表
id、详细信息、msg_num
物理表
id、详细信息、msg_num
所以我首先尝试选择“students”表,并根据“students”表中的“course_num”和“msg_num”值,确定从一组表中选择哪个表我有(如上所示,“生物学”、“化学”和“物理学”表)。
“学生”表如下所示:
“生物学”表包含如下数据:
“化学”表如下所示:
“物理”表如下所示:
因此,我再次尝试将其设置为如果 'students' 表中 'course_num' 中的数字设置为 '0,1,2' ,那么它将动态选择相关表从我预先设置的数组列表中。这是我在下面尝试过的确切代码,但它没有正确同步。请让我知道我在这里做错了什么:
<div style="position:relative; margin:auto; width:400px; font-family:Poppins; font-size:16px; border:2px solid black; padding:10px; margin-top:100px;">
<?php
include 'db_connect.php';
$selected_courses = array("biology", "chemistry", "physics");
$sql1 = "SELECT * FROM students";
$result1 = $conn->query($sql1);
while($row1 = $result1->fetch_assoc())
$course = $selected_courses[$row1['course_num']];
$sql2 = "SELECT students.*, $course.*, FROM students, $course
WHERE students.msg_num = $course.msg_num";
$result2 = $conn->query($sql2);
$row2 = $result2->fetch_assoc();
echo "STUDENT NAME: ". $row2['name'] . "<br>";
echo "DETAILS: ". $row2['details'] . "<br>";
echo "MSG NUM: ". $row2['msg_num'] . "<br>";
echo "<br>";
$conn->close();
?>
</div>
【问题讨论】:
确保它可能是一个整数 -$selected_courses[ (int)$row1['course_num'] ];
?
您的架构已损坏。您应该将三个相同的课程表合并为一个,并附加一列来标识主题。然后您的查询可以使用JOIN
直接将学生链接到他们的课程,而无需选择特定的表。
@TangentiallyPerpendicular 你能给我一个例子来说明你的意思吗?我真的很想将每个表分开,然后在用复选框选择它们后将它们组合到一个主表中的队列中。也许你可以详细说明你的想法。感谢您的参与。
@AaronEsteban 该架构称为多对多关联,应类似于:students (id, name)
、courses (id, name)
、students_courses (student_id, course_id)
。其中students_courses
确定分配给任一方向的每个学生的课程。 EG:SELECT s.*, c.*, FROM students AS s LEFT JOIN students_courses AS sc ON sc.student_id = s.id LEFT JOIN courses AS c ON c.id = sc.course_id
您当前的方法是通过将表名作为“硬编码”变量注入的“风险”,并且会导致脆弱的设计模式。
【参考方案1】:
您的架构基本上是错误的,并且您的代码包含一个嵌套查询,这几乎总是错误的处理方式。
设置一个表并添加一个course_num
列,而不是三个具有不同课程数据的相同表。这使您可以将JOIN
学生直接发送到他们的详细信息行,并且您可以使用单个SELECT
和JOIN
来提取数据。
所以使用你的学生表和这个 courseDetails 表:
CREATE TABLE `courseDetails` (
`id` int NOT NULL AUTO_INCREMENT,
`msg_num` int NOT NULL,
`course_num` int NOT NULL,
`details` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
您可以像这样在两个表之间的公共列上加入:
select name, details, s.msg_num
from students s
join courseDetails d
on (s.course_num = d.course_num AND s.msg_num = d.msg_num);
要在单个查询中获得此输出:
name | details | msg_num |
---|---|---|
Adam Smith | Biology Details #0 | 0 |
John Wright | Chemistry Details #1 | 1 |
您可以根据需要改变 JOIN 条件并使用 WHERE 子句创建不同的输出,所有这些都来自两个基本表。
这将您的 PHP 代码简化为
include 'db_connect.php';
$sql1 = "select name, details, s.msg_num from students s join courseDetails d on (s.course_num = d.course_num AND s.msg_num = d.msg_num);";
$result1 = $conn->query($sql1);
while($row1 = $result1->fetch_assoc())
echo "STUDENT NAME: ". $row1['name'] . "<br>";
echo "DETAILS: ". $row1['details'] . "<br>";
echo "MSG NUM: ". $row1['msg_num'] . "<br>";
echo "<br>";
$conn->close();
?>
演示:https://www.db-fiddle.com/f/3cmTkGhEgiBEUZS7dFNvnz/0
【讨论】:
非常感谢您的回复和示例代码。我将审查您的建议,测试这个特定的示例,然后立即向您报告。再次感谢您的帮助和时间。 就同步表而言,您的示例代码似乎运行良好。然而,这让我想到了关于选择这些表的下一个问题。假设我想增加“msg_num”,当它达到所选课程的峰值“msg_num”(“course_num”以及每门课程中可用的消息)时,我将如何让每个学生切换到下一门课程达到每门课程的峰值“msg_num”后的队列(“course_num”)? 我目前的 'msg_num' 从 0 增加到每门课程的 'msg_num' 中可用的最大/峰值数,但我想让 'msg_num' 回到 0 并且使用“course_num”将学生切换到队列中的下一门课程,将数字增加 1 以选择队列中的下一门课程。我相信你知道我在说什么,但为了确定,我会给你举个例子...... 您可以选择课程中的消息数量并使用一些整数运算来增加消息编号和课程编号:update students s join (select course_num, count(msg_num) as msgCount from courseDetails group by course_num) d on (s.course_num = d.course_num) set s.course_num = s.course_num+((s.msg_num+1) DIV d.msgCount), s.msg_num = (s.msg_num+1) % d.msgCount where s.id = 1 ;
(这仅使用id
=1 更新学生)。
只需删除WHERE s.id=1
子句即可更新所有学生。您可能需要添加一些东西来处理最后一个msg_num
的最后一个course_num
的学生。您必须在更广泛的系统环境中弄清楚这一点。以上是关于PHP MySQL根据列/行值选择多个表的主要内容,如果未能解决你的问题,请参考以下文章