【问题标题】:comma separated value into array逗号分隔值到数组中
【发布时间】:2013-07-30 15:04:47
【问题描述】:

我正在为学生创建一个数据库。

我创建了一个表格“主题”

ID    NAME
1     Maths
2     Science
3     Biology
4     Social Studies

我创建了另一个表“学生”

ID    Name         Subject
1     Ram          1,2,3
2     Shyam        1,3,4
3     Hanuman      1,2,3,4

我想将学生的姓名检索到一个 php 页面中并显示他们的科目,我该怎么做:

Name          Subject
Ram           Maths, Science, Biology
Shyam         Maths, Biology, Social Studies 

等等

我是 PHP、MySQL 的新手。

【问题讨论】:

  • 您的数据库架构错误,您不应在单个字段中使用逗号分隔列表。您应该有一个 sudent-subject 表,其中包含学生 ID 和主题 ID
  • 这是一对多的关系 (http://stackoverflow.com/q/7799675/2493918)。

标签: php mysql database


【解决方案1】:
  1. 起点是从学生表中删除主题
  2. 并创建一个名为student-subject的“pivot-table

例如:

+------------+------------+
| student_id | subject_id |
+------------+------------+
| 1          | 1          |
| 1          | 2          |
| 1          | 3          |
| 2          | 1          |
+------------+------------+

【讨论】:

    【解决方案2】:

    就像其他人指出的那样,您的架构确实不是最佳的,但您可以使用此查询实现您想要做的事情:

    select st.Name, group_concat(su.name ORDER BY su.ID)
    from Students st
    inner join Subjects su on concat(',',st.Subject,',') like concat('%,',su.ID,',%')
    group by st.Name
    

    请参阅 SQLFIDDLE:http://sqlfiddle.com/#!2/79286d/8/0

    【讨论】:

      【解决方案3】:

      以下代码适用于您现在拥有的数据库结构,下面是更好的解决方案 php中最快的方法是尽可能少的选择信息。可以加入表,但是加入速度很慢,所以我们尝试其他方法。您可以为每门课程选择主题的名称,这样每次查询对数据库的负担就会减轻,但是您会分配一些小查询,所以您也不喜欢这样。

      我建议的方法选择所有主题并将它们存储在一个数组中。通过将key设置为与主题id相同,您可以通过该key进一步访问信息,速度非常快。

      // Select all subjects:
      $qSubj = "SELECT id,name FROM Subjects"; 
      $sSubj = mysql_query($qSubj) or die(mysql_error()); // note: die() isnt pretty, and mysql_ should be mysqli_
      // Set the variable which is going to store our information:
      $subjects = array();
      // For each row found, add a line:
      while($fSubj = mysql_fetch_assoc($sSubj)){
          $subjects[ $fSubj['id'] ] = $fSubj; // here we save it, $subjects[2] will have the information of 'Science'
      }
      
      // Now we have the subjects, we can continue to the larger table:
      $qStudent = "SELECT id,name,subjects FROM Students";
      $sStudent = mysql_query($qStudent ) or die(mysql_error()); // note: die() isnt pretty, and mysql_ should be mysqli_
      // Now we have selected the users, loop through them:
      while($fStudent = mysql_fetch_assoc($sStudent )){
          // Here you can do whatever you want :) Im not a fan of echoing in this stage of the code
          // I prefer storing everything in something like $template, and output it at the end
          echo $fStudent['name'].' has following subjects: ';
          $courses = explode(",", $fStudent['subjects']); // By exploding on the comma, youhave them seperatly:
          foreach($courses as $k =>$subject_id){ // for each subject, get the name
              echo $subjects[ $subject_id ]['name'].' '; // Here we can use the information we stored earlier
          }
      }
      

      更好的解决方案:
      您现在在 while() 中有一个 foreach() 来获取用户。如果你有几行,这没什么大不了的,但如果你有 100 多行要显示,这个 foreach 循环会使其变慢。更好的方法是添加另一个表,将它们链接起来:

      主题:id,姓名
      学生:身份证、姓名
      student_subject:student_id,subject_id。

      最后一个表与您的 student.subjects 列的作用大致相同,但这是在数据库中,而不是在 php 中的数组中。 PHP 和循环不是最好的朋友,您应该在 student_subject 的表中添加连接,并将学生的 while() 中的 foreach() 替换为查询以选择该学生的所有 subject_id。

      【讨论】:

      • 这比正确的架构和使用 JOINS 慢很多
      • 如果可以的话,我想看看一些例子。根据我的经验,这比加入要快得多。而且我使用的是中大型数据集,因此任何性能都会引人注目
      • 使用当前的表设置,这是我体验的最快方式。我同意你的观点,即这必须被规范化并添加另一个表来连接两者,因此学生中的 foreach() while() 不必工作。我不喜欢这样的 PHP 循环
      • 好吧,关键是当前的设置是错误的,改变它(通过标准化)不是更有意义吗?然后破解它。
      • 是的,但我为当前问题提供了一个答案 :) 我记得当我开始时,每个人都给了我我不理解的解决方案,我更喜欢一个可行的解决方案,然后是一个更合适的解决方案
      【解决方案4】:

      您还可以检索主题列,将结果分解为一个数组,然后通过 foreach 语句查找每个主题的名称。

      $subjects = array(1,2,3);
      
      foreach ($subjects as $subject){
          $result = $db->query("SELECT `name` FROM `Subjects` WHERE `ID` = $subject");
               while($row = $result->fetch_assoc()) {
                  echo $row['name'];
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        • 2018-01-19
        • 1970-01-01
        • 2013-04-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多