使用 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 中进行选择,然后离开加入到 assignmentsassignGrades @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 按字母顺序排列多维数组的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL 按字母顺序重新排列字符串中的字符 [关闭]

使用 swap 按字母顺序排列字符串数组

php之快速入门学习-11(数组排序)

按字母顺序排列字符串数组(甚至是 *ptr)

按字母顺序排列单词

JavaScript sort函数的使用