使用 SQL 或 PHP 按字母顺序排列多维数组
Posted
技术标签:
【中文标题】使用 SQL 或 PHP 按字母顺序排列多维数组【英文标题】:Alphabetizing multidimensional array with SQL or PHP 【发布时间】:2021-11-21 20:35:39 【问题描述】:我正在编写一个成绩册,我遇到了一些问题,我正试图弄清楚如何解决。
我有三个表在这个脚本中起作用:(1) “作业”表,其中包含有关每个作业的信息,(2) “assignGrades”表,其中包含学生的作业分数 (3) “学生” " 包含学生信息的表格。
现在,每当我向班级添加新学生时,问题就来了。从逻辑上讲,如果学生在期中加入课程,他们就不会被分配到今年早些时候的“过去的工作”。考虑到这一点,INNER JOIN 语句将没有“连接”。我已经尝试在这种情况下使用“LEFT JOIN”和“RIGHT JOIN”,但我没有任何运气。
每当我使用下面的 SQL 语句构建 php 数组时,都会遇到问题。如果在年中添加了一个学生,则他们没有正确按字母顺序排列到数组中,这来自 SELECT 语句及其组织方式。请参阅下面的学生“Amy Appleton”示例,该示例是在年中添加的,但字母顺序不正确。
我需要什么帮助/希望的最终结果:
我正在尝试确定如何按字母顺序排列我的$array
,以便按照姓氏的顺序进行组织。我已经确定我将通过重写我的 SQL 语句或通过使用某种 PHP usort
来实现这一点,尽管如果可能的话,我更愿意在 SQL 端组织数据。我最好的猜测是通过 LEFT JOIN 来实现这一点,但我已经尝试了我的 SQL 语句中可能的所有变体,但没有得到任何想要的结果。
使用的 SQL 语句:
SELECT students.firstName, students.lastName, assignments.assID, assignments.assEmoji, assignments.points, assignments.title, assignments.assigned, assignments.due, assignGrades.*
FROM students
LEFT JOIN assignGrades ON students.usid = assignGrades.usid
LEFT JOIN assignments ON assignGrades.assID = assignments.assID
WHERE subID=? OR subID IS NULL ORDER BY due, lastName, firstName
来自 PHP 的片段正在构建 $array
while ($row = mysqli_fetch_assoc($results))
$array['assignments'][$row['assID']]['assEmoji'] = $row['assEmoji'];
$array['assignments'][$row['assID']]['title'] = $row['title'];
$array['assignments'][$row['assID']]['points'] = $row['points'];
$array['assignments'][$row['assID']]['assigned'] = $row['assigned'];
$array['assignments'][$row['assID']]['due'] = $row['due'];
$array['students'][$row['usid']]['firstName'] = $row['firstName'];
$array['students'][$row['usid']]['lastName'] = $row['lastName'];
$array['students'][$row['usid']]['fullName'] = $row['firstName']." ". $row['lastName'];
if ($row['status'] == 'graded' || $row['status'] == 'missing')
$array['students'][$row['usid']]['earned'] = $array['students'][$row['usid']]['earned'] + $row['score'];
$array['students'][$row['usid']]['maxpts'] = $array['students'][$row['usid']]['maxpts'] + $row['points'];
$array['students'][$row['usid']]['submissions'][$row['assID']]['workID'] = $row['workID'];
$array['students'][$row['usid']]['submissions'][$row['assID']]['status'] = $row['status'];
if (isset($row['submitted'])) $array['students'][$row['usid']]['submissions'][$row['assID']]['submitted'] = $row['submitted'];
if (isset($row['method'])) $array['students'][$row['usid']]['submissions'][$row['assID']]['method'] = $row['method'];
if (isset($row['score'])) $array['students'][$row['usid']]['submissions'][$row['assID']]['score'] = $row['score'];
if (isset($row['score'])) $array['students'][$row['usid']]['submissions'][$row['assID']]['points'] = $row['points'];
if (isset($row['graded'])) $array['students'][$row['usid']]['submissions'][$row['assID']]['graded'] = $row['graded'];
if (isset($row['method'])) $array['students'][$row['usid']]['submissions'][$row['assID']]['method'] = $row['method'];
return $array;
来自 SQL 语句的示例 print_r($array)
(Amy Appleton 应该出现在 $array['students']
的顶部,因为她按字母顺序排在其他两个学生之前。但是,由于 assignGrades 上没有条目9 号作业表,她出现在底部)
Array
(
[assignments] => Array
(
[9] => Array
(
[assEmoji] => ✏️
[title] => Beginning of Year Activities
[points] => 10
[assigned] => 2021-08-16
[due] => 2021-08-20 15:00:00
)
[10] => Array
(
[assEmoji] => ✏️
[title] => Mid Year Project
[points] => 10
[assigned] => 2021-09-23
[due] => 2021-09-30 15:00:00
)
)
[students] => Array
(
[11] => Array
(
[firstName] => Zeke
[lastName] => Lee
[fullName] => Zeke Lee
[earned] => 103
[maxpts] => 120
[submissions] => Array
(
[9] => Array
(
[workID] => 539
[status] => graded
[submitted] => 2021-08-17 08:15:48
[method] => wall
[score] => 9
[points] => 10
[graded] => 2021-09-22 10:26:54
)
[10] => Array
(
[workID] => 541
[status] => graded
[submitted] => 2021-09-23 08:15:48
[method] => wall
[score] => 9
[points] => 10
[graded] => 2021-09-23 10:26:54
)
)
)
[12] => Array
(
[firstName] => John
[lastName] => Smith
[fullName] => John Smith
[earned] => 91
[maxpts] => 110
[submissions] => Array
(
[9] => Array
(
[workID] => 540
[status] => graded
[submitted] => 2021-08-17 08:45:48
[method] => wall
[score] => 7
[points] => 10
[graded] => 2021-09-22 10:28:54
)
[10] => Array
(
[workID] => 590
[status] => graded
[submitted] => 2021-09-23 09:15:48
[method] => wall
[score] => 9
[points] => 10
[graded] => 2021-09-23 11:24:54
)
)
)
[13] => Array
(
[firstName] => Amy
[lastName] => Appleton
[fullName] => Amy Appleton
[earned] => 91
[maxpts] => 110
[submissions] => Array
(
[10] => Array
(
[workID] => 913
[status] => graded
[submitted] => 2021-09-23 10:45:48
[method] => wall
[score] => 7
[points] => 10
[graded] => 2021-09-23 12:31:54
)
)
)
)
)
数组结构:
$array['assignments'][assID][详情]
$array['students'][usid][详情]
$array['students'][usid]['submissions'][assID][详情]
SQL 表结构的屏幕截图
来自 SQL 查询的 CSV 转储屏幕截图
【问题讨论】:
您的查询是从 assignments 中选择的,这对于 Amy Appleton 来说是空的。您应该从 students 中进行选择,然后离开加入到 assignments 和 assignGrades。 @waterloomatt 对,我也是这么想的。我尝试了这个查询,但得到了相同的结果。FROM students LEFT JOIN assignGrades ON students.usid = assignGrades.usid LEFT JOIN assignments ON assignGrades.assID = assignments.assID
对。所以现在,Amy 应该出现在结果集中,但她的作业和成绩将是空的,因此您需要更改您的 PHP 来解决这个问题。进行此更改后,也许可以使用更多详细信息编辑您的问题。
@waterloomatt 我不相信问题出在 PHP 上。每当我在 MySQL 中运行 SQL 语句时,“查询结果”中没有条目表明发生了左连接(即:只有一个名称,没有分配/等级详细信息)。从查询中删除指向 CSV 转储的链接是否有帮助?
不,请使用这些详细信息编辑您的问题。请包括所有相关信息,这样我们就不需要在这里进行扩展聊天。您的查询是否过滤了WHERE subID=?
的主题? Amy 永远不会出现在那里,因为她没有任何 assignments.subID。另外,请包括您想要的输出应该是什么样子。根据这一点,使用多个查询来获得所需的数据结构可能会更容易。
【参考方案1】:
我看到的主要问题是您的查询试图做太多事情。它试图按特定顺序(按到期)获得作业,以及按不同顺序(按姓氏、名字)获得学生和他们的提交。出于这个原因,我会将其分解为 2 个单独的查询。您可以稍后组合数据集以制作最终的数据结构。
-
检索分配并在截止日期之前对它们进行排序。这是一个非常简单的查询,结果集可以直接使用。
检索所有学生及其提交(如果存在),并按姓、名排序。然后,在 PHP 中,将数据集操作为您需要的格式。
伪代码
// Get assignments. These can be used directly in your data structure `$combined`.
//
// Order by due date
$assignments = SELECT ... FROM assignments
WHERE ...
ORDER BY due;
// Get students and their assignments. These need to be manipulated to fit your
// requirements. Use a left join here because a student may not have started
// an assignment yet.
//
// Order by lastName, firstName
$students = SELECT ... FROM students a
LEFT JOIN assignGrades b ON b.usid = a.usid
ORDER BY lastName, firstName;
// See http://sandbox.onlinephpfunctions.com/code/9460c51954f8ea00f7ba75adadfcbf91fc03076e
// Loop over the student/submission dataset and manipulate it.
$studentMapping = [];
foreach($students as $row)
// Build up student data if it doesn't already exist.
// Importantly, create an empty submissions element. If the student's
// submission doesn't exist, this is what will be returned.
$student = $studentMapping[$row['usid']] ?? [];
if (empty($student))
$student = [
'firstName' => $row['lastName'],
'lastName' => $row['lastName'],
...
'submissions' => [],
];
// Build up submissions data for the student if they have submitted an assignment.
// If they haven't submitted an assignment yet, their submissions array will remain empty.
if (!empty($row['assignment_id']))
$student['submissions'][] = [
'assignmentId' => $row['assignment_id'],
'status' => $row['status'],
...
];
// Finally, assign the student (and their submissions) to the $studentMapping array.
$studentMapping[$row['usid']] = $student;
// Now combine them into your final datastructure.
$combined = [
'assignments' => $assignments,
'students' => $studentMapping,
];
【讨论】:
以上是关于使用 SQL 或 PHP 按字母顺序排列多维数组的主要内容,如果未能解决你的问题,请参考以下文章