PHP MYSQL приводит к таблице

#php #html #mysql #for-loop

#php #HTML #mysql #for-цикл

Вопрос:

У меня есть запрос PHP / MySQL, который возвращает следующее:

 array ( 'name' => 'Jess', 'month' => '2020-03-31 12:28:00', 'count' => '1', )
array ( 'name' => 'Bob', 'month' => '2020-04-31 12:28:00', 'count' => '2', )
array ( 'name' => 'Tom', 'month' => '2020-05-31 12:28:00', 'count' => '2', )
array ( 'name' => 'Bob', 'month' => '2020-05-31 12:28:00', 'count' => '2', )
  

Месяцы возвращаются упорядоченным образом (например, записи за январь всегда предшествуют записям за февраль).
Однако не каждый пользователь будет получать результат каждый месяц (см. Выше).

И я хочу, чтобы мои данные представлялись такими, как это, в таблице html:

 Month Jess Bob Tom
March   1   
April       2   
May         2   2
  

Вот моя (нерабочая) попытка:

 <?php

/*loop through all customers and print out each induvidual users performance*/


$con = mysqli_connect("localhost","root","","perfmon");

if (mysqli_connect_errno()) {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  exit();
}


//main query for customer names
if ($customers = mysqli_query($con, "SELECT Distinct(customer_name) FROM slog ORDER BY customer_name DESC;")) {

    while($row=mysqli_fetch_assoc($customers))
    {
        $name = $row["customer_name"];
        print("<b>".$name." </b><br>");
        $total = 0;
        $cur_month = NULL;
        $namepos = array();
        $th = "<th>Month</th>";
        $tr = "";
        
        
        $npcount = 0;
        
            //Loop over the customer names, and pull the modified count per user.
            if ($user_perf = mysqli_query($con, "select modified_by as name, created_date as month, count(modified_by) as count from slog where customer_name = '$name' group by modified_by, MONTH(created_date) order by month;")) {

                while($row=mysqli_fetch_assoc($user_perf))
                {
                    //Assign variables from mysql results
                    $month = date("F",strtotime($row["month"]));
                    $name = $row["name"];
                    $count = $row["count"];
                    $total  =  $row["count"];   
                    
                    //Only add the month once!
                    if($cur_month != $month){
                        $cur_month = $month;
                        $tr .= "</tr><tr><td>" . $cur_month. "</td>";
                        //print($cur_month . "<br>");
                    }
                    
                    //store the username 'position' to build a table (this determines how many spaces are needed.)
                    if(!array_key_exists($name,$namepos))
                    {
                        $namepos[$name] = $npcount;
                        $npcount  = 1;
                        $th .= "<th>" .$name . "</th>";
                    }
                    
                    //add details to tr in correct pos
                    for( $i = 0; $i < $namepos[$name]; $i  ){
                        $tr .= "<td></td>";
                    }
                    $tr .= "<td> ".$count." </td>";
                    
                    
                    
                    //print("amp;emsp;".$name . " " . $count . " <br>");

                }
                print("<table  border='1'><tr>". $th . "</tr>" . $tr . "</table>");
                
                print("<br>Total: ".$total." <br><br> ");
                mysqli_free_result($user_perf);
            }

      
      
    }

  mysqli_free_result($customers);
}









mysqli_close($con);

?>
  

Что, к сожалению, приводит к таким результатам, как это:-
введите описание изображения здесь

Каков наилучший способ добиться этого?Я попытался сохранить позицию каждого пользователя в заголовках таблицы, но тогда трудно определить, сколько пустых столбцов добавить до и запись (см. Изображение выше).

Комментарии:

1. Пришло время научиться использовать JOIN s

2. $tr .= "</tr><tr><td>" . $cur_month. "</td>" измените это на $tr .= "<tr><td>" . $cur_month. "</td></tr>";

3. Привет, Пратик, это, похоже, не решило проблему: imgur.com/hptWymr

4. Привет, Сид, можешь подробнее рассказать о JOIN? Я полностью за обучение, поэтому, если вы могли бы порекомендовать, где я должен использовать объединения, тогда я доберусь до этого … спасибо

5. Выполнение запросов к базе данных внутри цикла в целом считается плохой практикой. Вместо того, чтобы сначала выбирать своих пользователей, а затем выбирать данные для каждого отдельного пользователя внутри цикла поверх них, вы должны для начала объединить все необходимые вам данные в один запрос.

Ответ №1:

просто быстрое обновление. Мне удалось получить то, что я хотел, с помощью следующего кода

 <?php

/*loop through all customers and print out each induvidual users performance*/


$con = mysqli_connect("localhost","root","","perfmon");

if (mysqli_connect_errno()) {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  exit();
}


//main query for customer names
if ($customers = mysqli_query($con, "SELECT Distinct(customer_name) FROM slog ORDER BY customer_name DESC;")) {

    while($row=mysqli_fetch_assoc($customers))
    {
        //Name of customer
        $name = $row["customer_name"];
        //Print customer name
        print("<b>".$name." </b><br>");
        //Used to display total jobs
        $total = 0;


        $user_list = array("Month");
        $monthlist = array();
        $st_array = array();

        
        
            //Loop over the customer names, and pull the modified count per user.
            if ($user_perf = mysqli_query($con, "select modified_by as name, created_date as month, count(modified_by) as count from slog where customer_name = '$name' group by modified_by, MONTH(created_date) order by month;")) {

                while($row=mysqli_fetch_assoc($user_perf))
                {
                    $month = date("F",strtotime($row["month"]));
                    $name = $row["name"];
                    $count = $row["count"];
                    $total  =  $row["count"];   
                    
                    //make our left column (months)
                    if(!in_array($month, $monthlist)){
                        array_push($monthlist, $month);
                    }
                    
                    //Collect all unqiue users, to make our headers array. also stores the order theyre in.
                    if(!in_array($name, $user_list)){
                        array_push($user_list, $name);
                    }
                    
                    //make a 2d array of all data 
                    $tmp = [$month, $name, $count];
                    array_push($st_array, $tmp);
                    
                }
                
                /**Process fetched data **/
            
                $row = "";
                $previous_pos = 1; 
                $fe = True;
                
                //Print each unique user as a table header
                print("<table border='1'>");
                print("<tr>");
                foreach ($user_list as $th){
                    print("<th>".$th."</th>");
                }
                print("</tr>");
                
                //Loop the month array
                foreach ($monthlist as $td){
                    //Loop the user array
                    foreach ($user_list as $usr){
                        //Loop our "2d" array (an array containing Month,User,Count)
                        foreach($st_array as $array_2d){
                            
                            //If we match the correct month and user, return the count value. This ensures the users return in the correct order.
                            if ($array_2d[0] == $td amp;amp; $array_2d[1] == $usr){
                                
                                //Pos - Get the current position of the selected user.
                                //Establish how many empty entries need to come before. E.g. User in col 1 has no empty entries infront. User in column2 has 1 entry empty infront (if column 1 is empty).
                                $pos = array_search($usr, $user_list);
                                if ($previous_pos != $pos){
                                    
                                    $row .= str_repeat("<td>0</td>", ($pos-$previous_pos-1));

                                }
                                //Assign our previous position
                                $previous_pos = $pos;
                                
                                //If our first entry isn't in column 1, add an extra 0.
                                if($pos!==1 amp;amp; $fe)
                                    $row .= "<td>0</td>";
                                $fe = False;
                                //Add the data
                                $row .= "<td>".($array_2d[2])."</td>";  //change to [1] for debug
                            }
                            
                        }
                    }
                    
                    //Print the table row.
                    print("<tr><td>".$td ."</td>" . $row ."</tr>");
                    //Reset our variables.
                    $row = "";
                    $fe=True;
                    $previous_pos = 1;
                    $first_result  = True;
                }
                print("</table></br>");
                mysqli_free_result($user_perf);

            }

    }

  mysqli_free_result($customers);
}
mysqli_close($con);

?>
  

По сути, я создал 3 массива. Массив пользователей, массив месяцев и массив всех данных (3D-массив). Я использую месяцы и пользователей для записи порядка, в котором должны быть представлены таблицы. Затем я перебираю свой 3D-массив и печатаю соответствующие данные.

Несмотря на отрицательные голоса, я хотел бы поблагодарить вас всех за предложение вашей помощи. Если у вас есть какие-либо рекомендации, пожалуйста, дайте мне знать.